Linux bash脚本:将ls与glob一起使用,并在变量中获取输出不起作用

时间:2018-12-13 10:13:44

标签: bash glob ls

在CentOS 7机器上,我有一个包含2个文件的文件夹,其名称如下:

myapp-nightly__v3.0-SNAPSHOT__b59__lite.zip
myapp-nightly__v3.0-SNAPSHOT__b59.zip

这些文件每天晚上都会删除并生成,并且“ b”之后的数字(在上面的示例中为59)将递增。

我想要一个bash脚本文件,在该文件中我可以通过一个变量获取不包含“ _lite”的文件的名称(在上面的示例中,该文件名为“ myapp-nightly__v3” .0-SNAPSHOT__b59.zip“)

因此,我首先尝试在终端中使用“ ls”进行遍历,以了解其工作原理:

ls myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip

这将正确输出“ myapp-nightly__v3.0-SNAPSHOT__b59.zip”。

然后,我尝试制作一个简单的bash脚本,该脚本运行上述命令,并将其输出存储在变量中:

#!/bin/bash
MYAPP_KIT_FULL_PATH=$(ls myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip)
echo "MYAPP_KIT_FULL_PATH=$MYAPP_KIT_FULL_PATH"

这给了我以下错误:

./test.sh: command substitution: line 3: syntax error near unexpected token `('
./test.sh: command substitution: line 3: `ls myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip)'

所以我的问题是,如何在bash脚本中正确执行这样的“ ls”命令,并将其输出存储在变量中?由于glob字符,这在bash中不起作用吗?

附加说明:

  • 我知道错误消息显示“第3行”,但是我很确定它指向第2行(第3行只是执行回显)。即使我从脚本中完全删除了第3行(因此脚本只有2行),它仍然会给出有关第3行的错误

2 个答案:

答案 0 :(得分:3)

您可以使用find:

find dir -maxdepth 1 -name 'myapp-nightly__v3.0-SNAPSHOT__b*.zip' -not -name '*lite.zip'

要将目标文件解压缩到当前目录中:

find dir -maxdepth 1 -name 'myapp-nightly__v3.0-SNAPSHOT__b*.zip' -not -name '*lite.zip' -exec unzip {} \;

答案 1 :(得分:1)

您正在使用扩展的glob(通配符)表达式,但错误表明您未启用扩展的glob。您可以在开头添加shopt -s extglob。而且,您确实shouldn't parse the output of ls

在bash中有几种选择可以做到这一点。 @Aaron已经展示了如何使用find,因此我将提供几个纯bash选项。首先,您可以只使用一个简单的通配符表达式(否ls)并将结果捕获到数组中:

#!/bin/bash
shopt -s extglob
myapp_kit_full_paths=(myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip)
# Operate on just the first match:
unzip "${myapp_kit_full_paths[0]}"
# Operate on *all* matches (in case there are several):
for file in "${myapp_kit_full_paths[@]}"
    unzip "$file"
done

(顺便说一句,请注意,我在这里使用了小写的变量名。有一堆具有特殊含义的全大写字母名称,偶然使用其中的一个会引起麻烦;因此,小写和混合大小写的变量名为了您自己的目的更安全。)

另一种选择是直接在for语句中扩展全局表达式:

#!/bin/bash
shopt -s extglob
for myapp_kit_full_path in myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip
    unzip "$myapp_kit_full_path"
done