109

I want to insert in my script a value (string) that I would read from a text file.

For example, instead of:

echo "Enter your name"
read name

I want to read a string from another text file so the interpreter should read the string from the file and not the user input.

2
  • 2
    What does your text file look like? Is the entire file 1 variable or are they KEY=VALUE pairs? The solutions are quite different (if it's the latter, Takkat's answer applies, the former Radu's)
    – kiri
    Oct 28, 2013 at 11:37
  • 1
    @CiroSantilli it is not crossposted if it was posted by a different user, there is no such thing as a "cross-site duplicate". The only thing that should be avoided is the same question asked by the same user on different sites.
    – terdon
    Mar 24, 2014 at 17:52

12 Answers 12

152

To read variables from a file we can use the source or . command.

Lets assume the file contains the following line

MYVARIABLE="Any string"

we can then import this variable using

#!/bin/bash

source <filename>
echo $MYVARIABLE
8
  • 30
    One reason why you might not want to do it this way is because whatever is in <filename> will be run in your shell, such as rm -rf /, which could be very dangerous.
    – Mark
    Jan 10, 2015 at 2:57
  • 1
    Deserve to be marked as answer
    – Ali
    Oct 27, 2015 at 4:44
  • 8
    Late to the party, but, no, it doesn't deserve to be marked up OR as the answer. This sources another bash source file which is NOT what the OP asked for. He asked how to read the contents of a FILE into a variable. NOT how to execute another script which sets a variable. The correct answer is the one below. name=$(cat "$file") .
    – RichieHH
    Nov 24, 2015 at 12:54
  • 4
    OTOH, it is the answer to the question I asked google and google brought me here. Weird times, eh? Jul 10, 2017 at 18:04
  • 2
    You can use sed to add local keyword and make the script a bit safer and not polute your global scope. So inside a a function do cat global_variables.sh | sed -e 's/^/local /' > local_variables.sh and then use . ./local_variables.sh. Whatever you import in the function will only be available in that function. Note that it assumes global_variables.sh only contains one variable per line.
    – Nux
    Jun 14, 2018 at 11:46
85

Considering that you want all the content of your text file to be kept in your variable, you can use:

#!/bin/bash

file="/path/to/filename" #the file where you keep your string name

name=$(cat "$file")        #the output of 'cat $file' is assigned to the $name variable

echo $name               #test

Or, in pure bash:

#!/bin/bash

file="/path/to/filename"     #the file where you keep your string name

read -d $'\x04' name < "$file" #the content of $file is redirected to stdin from where it is read out into the $name variable

echo $name                   #test
7
  • 1
    I dont want to display the variable, I want that this variable should be read by the script for further processing. I have tried awk which reads line by line.
    – user208413
    Oct 28, 2013 at 8:48
  • 1
    Ok, delete echo $name . I use it just for test. Next you can use $name variable for further processing anywhere you want in your script. Oct 28, 2013 at 8:51
  • 6
    @user208413 The value of $name variable is the string from your file assigned using cat $file command. What is not clear or so difficult to understand? Oct 28, 2013 at 9:36
  • 2
    It's redundant to use a seperate $file variable if you're only using it once to load the $name variable, just use cat /path/to/file
    – kiri
    Oct 28, 2013 at 10:05
  • 2
    Nothing about this solution answers the question. It ignores his mention of searching for a specific string in a different file, and instead converts an entire text file's contents into a shell variable. Amazing how many voters cannot read... Dec 22, 2020 at 15:40
21
name=$(<"$file") 

From man bash:1785, this command substitution is equivalent to name=$(cat "$file") but faster.

17

From within your script you can do this:

read name < file_containing _the_answer

You can even do this multiple times e.g. in a loop

while read LINE; do echo "$LINE"; done < file_containing_multiple_lines
2
  • 1
    or for a file with multiple items on each line . . . grep -v ^# file |while read a b c; do echo a=$a b=$b c=$c; done
    – gaoithe
    Sep 1, 2015 at 14:29
  • 1
    This reads the whole line of a file, not a variable declared within the file.
    – belvederef
    Oct 31, 2019 at 10:41
8

One alternative way to do this would be to just redirect standard input to your file, where you have all the user input in the order it's expected by the program. For example, with the program (called script.sh)

#!/bin/bash
echo "Enter your name:"
read name
echo "...and now your age:"
read age

# example of how to use the values now stored in variables $name and $age
echo "Hello $name. You're $age years old, right?"

and the input file (called input.in)

Tomas
26

you could run this from the terminal in one of the following two ways:

$ cat input.in | ./script.sh
$ ./script.sh < input.in

and it would be equivalent to just running the script and entering the data manually - it would print the line "Hello Tomas. You're 26 years old, right?".

As Radu Rădeanu has already suggested, you could use cat inside your script to read the contents of a file into a avariable - in that case, you need each file to contain only one line, with only the value you want for that specific variable. In the above example, you'd split the input file into one with the name (say, name.in) and one with the age (say, age.in), and change the read name and read age lines to name=$(cat name.in) and age=$(cat age.in) respectively.

4
  • I have the following script: vh = awk "NR==3{print;exit}" /var/www/test/test.txt with this I read line 3 from text file named test.txt. Once i get a string I want to use this string as an input for creating a directory
    – user208413
    Oct 28, 2013 at 10:18
  • 1
    Change that to vh=$(awk "NR==3 {print;exit}" /var/www/test.txt). You will then have the string saved in variable $vh, so you can use it like so: mkdir "/var/www/$vh" - this will create a folder with the specified name inside /var/www. Oct 28, 2013 at 11:09
  • I have done this way but it still cant create the folder :(
    – user208413
    Oct 28, 2013 at 11:34
  • @user208413: What error message(s) do you get? "It doesn't work" is, unfortunately, not a very helpful problem description... Oct 29, 2013 at 11:02
4

Short answer:

name=`cat "$file"`
4

I found working solution here: https://af-design.com/2009/07/07/loading-data-into-bash-variables/

if [ -f $SETTINGS_FILE ];then
    . $SETTINGS_FILE
fi
1
  • The slides are no longer available.
    – kris
    Mar 12, 2018 at 15:34
0

If you want to use multiple strings, you could go with:

path="/foo/bar";
for p in `cat "$path"`;
do echo "$p" ....... (here you would pipe it where you need it) 

OR

If you want the user to indicate the file

read -e "Specify path to variable(s): " path;
for p in 'cat "$path"';
do echo "$p" ............................
0
#! /bin/bash
#  (GPL3+) Alberto Salvia Novella (es20490446e)


variableInFile () {
    variable=${1}
    file=${2}

    source ${file}
    eval value=\$\{${variable}\}
    echo ${value}
}


variableInFile ${@}
0

I use this to get a single variable from a file

GET_VAR=$(grep --color=never -Po "^${GET_VAR}=\K.*" "${FILE}" || true)

When GET_VAR is not found in ${FILE} it will be blank rather than causing an error thanks to the || true.

It uses grep -P which is in GNU grep but not default in all grep at the time of writing this.

1
  • This doesn't seem to work for me. The initial $ throws an error for illegal character
    – ginna
    Sep 25, 2019 at 17:39
0

This question is a bit vague, hence a lot of the bizarre responses; in fact, some of the answers on this page do not even address the original question whatsoever.

That said, if you want to source (read) a bash variable from a different file, the best solution is always to use a subshell so that no conflicts arise between your script and the file that is being read:

WORKING_VARIABLE=$(source /path/script.sh; echo $FILE_VARIABLE)

We use this method in SlickStack for sourcing the config file multiple times without conflicts.

If you plan to use multiple variables from the file or have other reasons to include the entirety of the other file in your current script, then you might source the entire file:

source /path/script.sh

But in non-bash-variable cases, such as the OP situation of wanting to read a simple "string" from a text file, neither of these solutions would work, and you'd have to use a solution that is tailored to the syntax of the code you are trying to read... for example, one of the examples on this page using grep or awk combinations, or @thom solution for reading a given line of a file using read.

TL;DR subshells are best for bash variables, otherwise it depends on the syntax of the file.... if you want to save the file contents as a bash variable, try cat as explained by @hellork.

0

Assuming a file /etc/os-release with these contents:

NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.17.2

To load just the ID variable, grep it to a pipe, then source the pseudo-file /dev/stdin:

grep ^ID= /etc/os-release | . /dev/stdin
printf "$ID"  # => alpine

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .