我缺少什么?
我想找出目录中有多少文件与给定模式匹配并将其分配给变量。
如果我直接在命令行上输入它,它就可以正常工作
ls /backups/system\ db\ files/temp/daily/backup_filename_202203*.tar.gz | wc -l
(注意,是*
创建备份的日期,例如01
、等)02
03
但一旦我将它添加到我的 bash 脚本中,它就会失败。
到目前为止我有:
base_dir="/backups/system\ db\ files/temp"
sub_dir="${base_dir}/daily"
filename_base="backup_filename_"
然后我尝试运行:
counter=$(ls ${sub_dir}/${filename_base_}202203*.tar.gz | wc -l)
或带引号:
counter=$(ls "${sub_dir}/${filename_base_}202203*.tar.gz" | wc -l)
第一个失败,因为它尝试根据空格分割它。第二个不扩展 来*
查找通配符。
我尝试过引用其中的一些内容,例如
counter=$(ls "${sub_dir}/${filename_base_}"202203*.tar.gz | wc -l)
但它再次忽略了通配符。
我一直在寻找,但我一生都找不到一种方法来获取匹配文件的总数。
答案1
您的问题是您的目录没有被调用/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[@]}
使用位置参数列表:
set -- "some/path to the/files"/*.txt
count=$#
在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
或者,如果您使用位置参数,
set -- "some/path to the/files"/*.txt
count=$#
if [ ! -e "$1" ] && [ ! -h "$1" ]; then
count=0
fi
如果否定-e
和-h
测试是真的对于结果列表中的第一个元素,则第一个元素不是现有文件,也不是损坏的符号链接。这意味着该模式没有匹配项。
答案2
当你已经引用它们时,不要转义空格,否则反斜杠将按字面意思理解:
base_dir="/backups/system\ db\ files/temp"
应该
base_dir="/backups/system db files/temp"
还有为什么你_
有${filename_base_}
?
你的最后一个命令应该有大概如果其他一切都正确,则有效:
counter=$(ls "${sub_dir}/${filename_base}"202203*.tar.gz | wc -l)
无论如何,你不应该解析ls
。
而是使用find
:
find "${sub_dir}" -name "${filename_base}202203*.tar.gz" -printf '.' | wc -c
或一个数组:
shopt -s nullglob
files=("${sub_dir}/${filename_base}"202203*.tar.gz)
echo "${#files[@]}"
您需要该nullglob
选项,否则结果将是1
没有文件与您的模式匹配,因为字符串将按字面意思处理。