相同命令的行为(在 Bash 下)-在控制台中逐个运行与作为单个脚本运行

相同命令的行为(在 Bash 下)-在控制台中逐个运行与作为单个脚本运行

在 OS X 10.11.1 上运行时,我在控制台中逐一执行以下一系列命令:

FILE="a b c.tiff"  # file in the current folder
VAR=$(mdls -name kMDItemContentCreationDate $FILE) # storing the creation time string  
TS=$(echo ${VAR[2]}; echo ${VAR[3]}  # saving the date and time only
echo $TS  

扩展工作得很好。输出显示:

2016-01-16 15:34:29

但是,当我将这些保存在脚本中并运行它时,评估过程中似乎出现了一些不同。

调试(使用重击)得出:

FILE='a b c.tiff'
mdls -name kMDItemContentCreationDate a b c.tiff
VAR='a: could not find a.'
echo
echo
TS=
echo

,因此我看到扩张的行为有所不同。

我担心的是为什么会出现这种差异以及我应该如何纠正我的脚本。谢谢。

答案1

我敢肯定您没有在控制台中运行过这些命令,否则您会得到相同的结果。这里有两个严重的问题,以及一些糟糕的脚本编写实践。首先是严重的问题:

  • 当您引用一个变量(例如$FILE)而没有用双引号括起来时,shell 会将其拆分为“单词”,然后展开所有通配符,然后再将其传递给命令。在本例中,这意味着 将a b c.tiff被拆分为“a”、“b”和“c.tiff”。这就是您收到“a:无法找到 a。”错误的原因。

    解决方案:除非您特别想要分词和通配符扩展,否则应将变量引用放在双引号中。(有些情况下,省略双引号是安全的,但跟踪它们会比它的价值更麻烦。只要养成使用双引号的习惯即可。)

  • 当你使用像这样的赋值时VAR=$(somecommand),它会将变量赋值为纯字符串,不是一个数组。要将其存储为数组,请在右侧使用括号,如VAR=( $(somecommand) )。请注意,由于$(somecommand)不在双引号中,因此它将被拆分成单词并进行通配符扩展,但在这种情况下,我们希望拆分单词(因此每个“单词”都存储在单独的数组元素中),并且输出格式足够可预测,通配符扩展不会做任何奇怪的事情来搞砸我们。所以这是少数可以省略双引号的情况之一。

修复这两个问题后,第二行变成:

VAR=( $(mdls -name kMDItemContentCreationDate "$FILE") )

现在,有些不良的脚本习惯实际上并没有造成麻烦:

  • 在赋值中TS=$(echo ${VAR[2]}; echo ${VAR[3]})(注意:我添加了缺失的右括号),命令替换和echo命令没有做任何有用的echo事情。它所做的是获取数组元素值,对它们进行单词拆分和通配符扩展(这里什么都不做),将它们作为参数传递给命令,获取这些命令的输出并将其收集到变量中。将两个字符串粘在一起需要做很多工作。只需使用`TS="${VAR[2]} ${VAR[3]}"。

    顺便说一句,它还做了一些有点奇怪的事情:它将字符串粘在一起,并在它们之间添加换行符。当您使用 打印它时echo $TS,它(再次)被拆分成单词,因此每行都被视为 的单独参数echo,这会在参数之间添加空格。最终结果:该echo命令实际上将换行符转换为空格。首先将其设置为空格,然后在使用它时将其双引号括起来会更简洁,这样您的脚本就不会依赖于两个恰好相互抵消的奇怪行为。

  • 最后,使用全大写变量并不安全。有许多全大写变量对 shell(和某些命令)具有特殊含义,如果您不小心使用其中一个,可能会得到奇怪的结果。典型的例子是将某个变量分配给 PATH,此时所有命令突然变得无法识别。很难跟踪所有魔法变量,因此只需使用小写变量即可,这样就安全了。

清理完所有这些后,我得到的脚本内容如下:

file="a b c.tiff"  # file in the current folder
var=( $(mdls -name kMDItemContentCreationDate "$file") ) # storing the creation time string as an array
ts="${var[2]} ${var[3]}"  # saving the date and time only
echo "$ts"

最后说明:如有疑问,请运行脚本shellcheck.net——它会指出许多标准的初学者错误并为您节省大量时间!

相关内容