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

Linux bash script: using ls with glob and getting output in variable not working

在我的 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" 命令,并将其输出存储在变量中?由于全局字符,这在 bash 中不起作用吗?

补充说明:

你可以使用 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 {} \;

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

在 bash 中有多种选择 "right"。 @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 语句中扩展 glob 表达式:

#!/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