26

我的 bash 脚本接收文件名(或相对路径)作为字符串,但必须从该文件中读取。如果我直接在脚本中将文件名声明为文字(不带引号),我只能从文件名中读取......这对于参数来说是不可能的,因为它们是以隐式字符串开头的。观察:

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

产量:

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

如上所述,我无法将命令行参数传递给上面的例程,因为我得到的行为与引用字符串的行为相同。

4

2 回答 2

49

这是扩展规则的~一部分。在 Bash 手册中明确指出,~引用 时不执行此扩展。

解决方法 1

不要引用~.

file=~/path/to/file

如果您需要引用文件名的其余部分:

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

(这在普通贝壳中是完全合法的。)

解决方法 2

使用$HOME而不是~.

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

顺便说一句:Shell 变量类型

您似乎对 shell 变量的类型有些困惑。

一切都是一个字符串。

重复,直到它沉入:一切都是一个字符串。(整数除外,但它们大多是 AFAIK 字符串之上的黑客攻击。还有数组,但它们是字符串数组。)

这是一个外壳字符串:"foo". 也是如此"42"。也是如此42。也是如此foo。如果您不需要引用事物,则不引用是合理的;谁想打字"ls" "-la" "some/dir"

于 2013-05-23T00:25:11.090 回答
1

仍然没有那么迷人,但对我有用:

home_folder="/home/$(logname)"

可以从那里工作...

于 2021-01-03T06:39:08.043 回答