我缺少什么?
我想找出目录中有多少文件与给定模式匹配并将其分配给变量。
如果我直接在命令行上输入它,它就可以正常工作
ls /backups/system\ db\ files/temp/daily/backup_filename_202203*.tar.gz | wc -l
Run Code Online (Sandbox Code Playgroud)
(注意,*
是创建备份的日期,例如01
、02
等03
)
但一旦我将它添加到我的 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)
但它再次忽略了通配符。
我一直在寻找,但我一生都找不到一种方法来获取匹配文件的总数。
您的问题是您的目录没有被调用/backups/system\ db\ files/temp
,而是被调用了backups/system db files/temp
。当引用字符串时,反斜杠成为字符串的一部分。由于您引用了该字符串,因此无需转义空格。filename_base
您在一些地方的变量拼写也错误(带有尾随下划线)。
您也不需要使用ls
和wc
来计算与 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)
在bash
shell 中,您必须设置nullglob
shell 选项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
测试为真,则第一个元素不是现有文件,也不是损坏的符号链接。这意味着该模式没有匹配项。
当你已经引用它们时,不要转义空格,否则反斜杠将按字面意思理解:
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
没有文件与您的模式匹配,因为字符串将按字面意思处理。