Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash: interpret string variable as file name/path

My bash script receives a filename (or relative path) as a string, but must then read from that file. I can only read from a filename if I declare it as a literal directly in the script (without quotes)...which is impossible for arguments since they are implicitly strings to begin with. Observe:

a="~/test.txt" #Look for it if [[ -a $a ]] ; then     echo "A Found it" else     echo "A Error" fi #Try to use it while read line; do     echo $line done < $a  b='~/test.txt' #Look for it if [[ -a $b ]] ; then     echo "B Found it" else     echo "B Error" fi #Try to use it while read line; do     echo $line done < $b  c=~/test.txt #Look for it if [[ -a $c ]] ; then     echo "C Found it" else     echo "C Error" fi #Try to use it while read line; do     echo $line done < $c 

YIELDS:

A Error ./test.sh: line 10: ~/test.txt: No such file or directory B Error ./test: line 12: ~/test.txt: No such file or directory C Found it Hello 

As stated above, I can't pass a command line argument to the routines above since I get the same behavior that I get on the quoted strings.

like image 368
Keith Wiley Avatar asked May 23 '13 00:05

Keith Wiley


People also ask

Can’t pass filenames with spaces in Bash?

However, most users will still have issues while trying to handle passing filenames with spaces in bash. This is because spaces are not considered the same in bash as they are in file names. Why Filename with Spaces is not Recognized by Bash?

How does Bash interpret domain_ as a variable name?

domain="example" sub="foo" if [ -f /opt/nginx/conf.d/com_$domain_$sub.conf ] cat <<EOF > /opt/nginx/conf.d/com_$domain_$sub.conf some multiline content EOF fi In this case Bash interprets domain_ as the name of the variable to expand. It's a valid name for a variable. Expanding this name is not what you intended.

What happens if you unset a variable in Bash?

Using an unset variable is normally not an error. Invoke set -u and Bash will treat unset variables as errors (revert with set +u if needed). Treating unset variables as errors is useful for debugging, but also in defensive scripting.

How do I see the environment variables in a bash script?

To see the active environment variables in your Bash session, use this command: env | less. If you scroll through the list, you might find some that would be useful to reference in your scripts. How to Export Variables. When a script runs, it’s in its own process, and the variables it uses cannot be seen outside of that process.


2 Answers

This is part of the rules of ~-expansion. It is clearly stated in the Bash manual that this expansion is not performed when the ~ is quoted.

Workaround 1

Don't quote the ~.

file=~/path/to/file 

If you need to quote the rest of the filename:

file=~/"path with spaces/to/file" 

(This is perfectly legal in a garden-variety shell.)

Workaround 2

Use $HOME instead of ~.

file="$HOME/path/to/file" 

BTW: Shell variable types

You seem to be a little confused about the types of shell variables.

Everything is a string.

Repeat until it sinks in: Everything is a string. (Except integers, but they're mostly hacks on top of strings AFAIK. And arrays, but they're arrays of strings.)

This is a shell string: "foo". So is "42". So is 42. So is foo. If you don't need to quote things, it's reasonable not to; who wants to type "ls" "-la" "some/dir"?

like image 99
michaelb958--GoFundMonica Avatar answered Sep 28 '22 02:09

michaelb958--GoFundMonica


Still not as glamorous, but worked for me:

home_folder="/home/$(logname)" 

can work from there...

like image 38
Rob Hendricks Avatar answered Sep 28 '22 02:09

Rob Hendricks