我编写了一个脚本,其中写道:
COMMAND="/usr/bin/exiftool $PATH_NAME" .... 代码 .... 命令
变量 $PATH_NAME 在 while 循环内动态分配。该命令运行正常,直到遇到带有空格的文件(例如 PATH_NAME="Add Driver.png")。控制台输出为:
未找到文件:./Add 未找到文件:driver.png
命令应该是:
/usr/bin/exiftool./添加驱动程序.png
我认为问题是由 $PATH_NAME 中的空格引起的。我还尝试直接执行以下命令:
eval “/usr/bin/exiftool $PATH_NAME”
但输出错误相同。有什么办法可以解决这个问题吗?谢谢。
答案1
不要使用简单的字符串,而是使用数组来构建命令。数组提供了一个方便的接口:如果a
是数组,则"${a[@]}"
(注意引号)会扩展为的每个元素a
,没有额外的字段拆分或通配符(因此空格和通配符之类的东西应该保持完整)。
例子:
$ a=(printf "|%s|\n" "foo bar" "*")
$ echo ${a[@]}
printf |%s|\n foo bar bin boot dev etc home lib lib64 lost+found mnt opt proc root run sbin srv sys tmp usr var
注意 是如何扩展的,以及和*
之间的多余空格是如何丢失的。但是使用,这些空格被保留了下来:foo
bar
"${a[@]}"
$ echo "${a[@]}"
printf |%s|\n foo bar *
这对于构建命令来说非常理想。现在,您可以执行以下操作:
$ "${a[@]}"
|foo bar|
|*|
看到了吗?论点被完美地保留了下来。
因此,请这样做:
COMMAND=(/usr/bin/exiftool "$PATH_NAME")
"${COMMAND[@]}"
答案2
glenn jackman 的观点很有道理。但是,为了解决你的直接用例,反引号怎么样?像这样:
`echo $COMMAND`
例如,这个有效:
COMMAND='ls /'
`echo $COMMAND`
答案3
有关 Bash 如何解释空格的更多详细解释,我建议阅读此文:Bash 变量和命令替换
清洁解决方案
如果变量包含特殊字符,扩展变量可能会导致意外的,有时甚至是灾难性的后果:
user@host:~$ do_something $some_variable
在双引号内扩展变量可以避免此类问题:
user@host:~$ do_something "$some_variable"
解释
这里遇到的案例在帖子的最后有描述:
未加引号的变量的危险
在理想世界中,每个人都会保持其字符串值简短并且没有空格/换行符或任何其他特殊字符。
[...]
但是,当人们开始在文件名中添加特殊字符(例如空格)时,扩展变量而不使用双引号可能会很危险。
[...]
这里的主要内容是:尽可能使用双引号引用变量。