bash 使用通配符计算路径中的文件并分配给变量

IGG*_*GGt 2 bash shell-script

我缺少什么?

我想找出目录中有多少文件与给定模式匹配并将其分配给变量。

如果我直接在命令行上输入它,它就可以正常工作

ls /backups/system\ db\ files/temp/daily/backup_filename_202203*.tar.gz | wc -l
Run Code Online (Sandbox Code Playgroud)

(注意,*是创建备份的日期,例如010203

但一旦我将它添加到我的 bash 脚本中,它就会失败。

到目前为止我有:

base_dir="/backups/system\ db\ files/temp" 
sub_dir="${base_dir}/daily"
filename_base="backup_filename_"
Run Code Online (Sandbox Code Playgroud)

然后我尝试运行:

counter=$(ls ${sub_dir}/${filename_base_}202203*.tar.gz | wc -l)
Run Code Online (Sandbox Code Playgroud)

或带引号:

counter=$(ls "${sub_dir}/${filename_base_}202203*.tar.gz" | wc -l)
Run Code Online (Sandbox Code Playgroud)

第一个失败,因为它尝试根据空格分割它。第二个不扩展*来查找通配符。

我尝试过引用其中的一些内容,例如

counter=$(ls "${sub_dir}/${filename_base_}"202203*.tar.gz | wc -l)
Run Code Online (Sandbox Code Playgroud)

但它再次忽略了通配符。

我一直在寻找,但我一生都找不到一种方法来获取匹配文件的总数。

Kus*_*nda 6

您的问题是您的目录没有被调用/backups/system\ db\ files/temp,而是被调用了backups/system db files/temp。当引用字符串时,反斜杠成为字符串的一部分。由于您引用了该字符串,因此无需转义空格。filename_base您在一些地方的变量拼写也错误(带有尾随下划线)。

您也不需要使用lswc来计算与 shell 模式匹配的名称数量。请记住,文件名中可以​​包含换行符,并且wc -l计算的是换行符,而不是文件名。

要查看 shell 模式有多少个匹配项,您所需要做的就是将模式扩展为数组或位置参数列表,然后查看该数组或列表的长度。

使用具有示例模式的数组:

list=( "some/path to the/files"/*.txt )

count=${#list[@]}
Run Code Online (Sandbox Code Playgroud)

使用位置参数列表:

set -- "some/path to the/files"/*.txt

count=$#
Run Code Online (Sandbox Code Playgroud)

bashshell 中,您必须设置nullglobshell 选项shopt -s nullglob来正确处理空目录(如果该模式不匹配任何内容,则该模式通常不会展开)。

如果没有设置nullglob,您可以使用以下命令来测试是否没有匹配项

list=( "some/path to the/files"/*.txt )
count=${#list[@]}

if [ ! -e "${list[0]}" ] && [ ! -h "${list[0]}" ]; then
    count=0
fi
Run Code Online (Sandbox Code Playgroud)

或者,如果您使用位置参数,

set -- "some/path to the/files"/*.txt
count=$#

if [ ! -e "$1" ] && [ ! -h "$1" ]; then
    count=0
fi
Run Code Online (Sandbox Code Playgroud)

如果结果列表中的第一个元素的否定-e-h测试为,则第一个元素不是现有文件,也不是损坏的符号链接。这意味着该模式没有匹配项。


pLu*_*umo 5

当你已经引用它们时,不要转义空格,否则反斜杠将按字面意思理解:

base_dir="/backups/system\ db\ files/temp" 
Run Code Online (Sandbox Code Playgroud)

应该

base_dir="/backups/system db files/temp"
Run Code Online (Sandbox Code Playgroud)

还有为什么你_${filename_base_}

如果其他一切都正确的话,你的最后一个命令可能应该有效:

counter=$(ls "${sub_dir}/${filename_base}"202203*.tar.gz | wc -l)
Run Code Online (Sandbox Code Playgroud)

无论如何,你不应该解析ls.

而是使用find

base_dir="/backups/system\ db\ files/temp" 
Run Code Online (Sandbox Code Playgroud)

或一个数组:

base_dir="/backups/system db files/temp"
Run Code Online (Sandbox Code Playgroud)

您需要该nullglob选项,否则结果将是1没有文件与您的模式匹配,因为字符串将按字面意思处理。