bash + 测试文件夹是否为空但排除带前导点的文件

bash + 测试文件夹是否为空但排除带前导点的文件

我们使用以下方法来验证文件夹是否为空:

[[ "$(ls -A /var/folder)" ]] && echo "not empty"

在 上/var/folder,我们执行了以下操作:

ls -l /var/folder
total 0

事实上我们没有得到任何输出。

但是当我们运行 shell 时

[[ "$(ls -A /var/folder)" ]] && echo "not empty"

然后它打印

not empty

所以我们发现该文件夹包含带有前导点的文件,如下所示:

ls -la /var/folder
total 4
drwxr-xr-x  2 kafka kafka   47 Jan 19 17:23 .
drwxr-xr-x 42 kafka kafka 4096 Jan 19 10:25 ..
-rw-r--r--  1 kafka kafka    0 Jan 19 17:22 .kafka_cleanshutdown
-rw-r--r--  1 kafka kafka    0 Jan 19 15:16 .lock

所以问题是如何验证文件夹是否为空但忽略以“.”开头的文件的存在。

答案1

如果您不想看到点文件,请忽略-A!

[[ "$(ls /var/folder)" ]] && echo "not empty"

但你甚至不需要使用ls;您可以完全在 shell 中执行此操作:

file_list=(/var/folder/*)
[[ "${file_list[*]}" != "/var/folder/*" ]] && echo "not empty"

这扩展了/var/folder/*通配符模式(“glob”)。如果有非隐藏文件,那么file_list将是它们的名称列表。如果没有,则file_list只是文字 string /var/folder/*

这里有一个错误:如果目录包含一个名称为literal的文件*,那么${file_list[*]}将是文字字符串/var/folder/* ,上面的代码将失败(表明该目录为空)。你可以通过这样做来解决这个问题

shopt -s nullglob
file_list=(/var/folder/*)
[[ "${file_list[*]}" != "" ]] && echo "not empty"
shopt -u nullglob

当然,强大的脚本会在开始时检查设置nullglob,然后在最后恢复该设置,而不是仅仅取消设置。

这是为 bash 编写的,不适用于所有 shell。

答案2

您可以展开*目录并计算它匹配的名称数量。如果它匹配零个名称,则该目录为空。默认情况下,该*模式与隐藏名称(“带有前导点的文件”)不匹配。

shopt -s nullglob

set -- /var/folder/*

if [ "$#" -eq 0 ]; then
    echo '/var/folder is empty'
fi

"$#"是位置参数列表中的元素数量,我们将其设置为set相关目录中的可见名称。

如果您愿意,您bash可以使用数组:

shopt -s nullglob

names=( /var/folder/* )

if [ "${#names[@]}" -eq 0 ]; then
    echo '/var/folder is empty'
fi

unset -v names

我们nullglob在上面的代码片段中设置,如果模式不匹配任何内容,则将其完全删除。不使用 using 的更便携的变体nullglob是像第一个变体一样使用set,然后测试$1是否存在:

set -- /var/folder/*

if [ ! -e "$1" ] && [ ! -h "$1" ]; then
    echo '/var/folder is empty'
fi

请注意,我们需要测试-hin 中的名称是否$1是符号链接,否则我们将无法检测损坏的符号链接。

相关内容