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.
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
~
.If you need to quote the rest of the filename:
(This is perfectly legal in a garden-variety shell.)
Workaround 2
Use
$HOME
instead of~
.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 is42
. So isfoo
. If you don't need to quote things, it's reasonable not to; who wants to type"ls" "-la" "some/dir"
?