我的父目录中有 150 个目录。其中一些有.txt
文件,另一些则没有。我想打印哪些文件夹没有文件.txt
。我怎样才能实现这个目标?
答案1
for dir in */; do
set -- "$dir"/*.txt
[ ! -e "$1" ] && printf '%s\n' "$dir"
done
这将循环当前目录中的所有目录。对于每个目录,它尝试.txt
使用set
.这会将位置参数( 、 等)设置$1
为$2
与模式匹配的文件的路径名,或者$1
如果它不匹配任何内容,则仅设置为模式本身。如果该文件名扩展的第一个结果不是现有文件的路径名,则打印目录的名称。
要对当前目录(包括当前目录)中的所有目录递归执行此操作:
find . -type d -exec sh -c '
for dir do
set -- "$dir"/*.txt
[ ! -e "$1" ] && printf "%s\n" "$dir"
done' sh {} +
这用作find
目录路径名的生成器。对于批量找到的目录路径名,执行与之前相同的循环,打印不包含任何名称以.txt
.
请注意,上面的两段代码都会检测到是否存在任何名称结尾为.txt
.如果您只是感兴趣常规文件(或常规文件的符号链接),然后使用以下内容作为循环体:
while [ "$#" -gt 0 ] && [ ! -f "$1" ]; do
shift
done
[ ! -e "$1" ] && ...as above...
包括隐文件名,例如使用bash -O dotglob -c
代替sh -c
with find
。这将使 shell 循环中的文件名通配也考虑以点开头的名称。在第一个变体中,如果您在 中运行循环,请确保设置dotglob
shell 选项。shopt -s dotglob
bash
答案2
我能够通过以下方式完成此任务:
#!/bin/bash
search_dir=~/tmp
dirs=( $( find "$search_dir" -type f -name "*.txt" -exec dirname {} \; | sort -u ) )
exclude=()
for dir in "${dirs[@]}"; do
exclude+=( -not -path "$dir" )
done
find "$search_dir" "${exclude[@]}" -type d
将变量更改search_dir
为您要使用的父目录。
然后它将dirs
数组设置为每个目录做包含 .txt 文件。
exclude
然后,每个目录都将以可以输入到 的格式添加到数组中find
。然后,我们再次搜索您的父目录以查找不在排除数组中的所有目录。