执行存储在 $variable 中的命令

执行存储在 $variable 中的命令

我编写了一个脚本,其中写道:

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

注意 是如何扩展的,以及和*之间的多余空格是如何丢失的。但是使用,这些空格被保留了下来:foobar"${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"

解释

这里遇到的案例在帖子的最后有描述:

未加引号的变量的危险

在理想世界中,每个人都会保持其字符串值简短并且没有空格/换行符或任何其他特殊字符。

[...]

但是,当人们开始在文件名中添加特殊字符(例如空格)时,扩展变量而不使用双引号可能会很危险。

[...]

这里的主要内容是:尽可能使用双引号引用变量

相关内容