我是Linux新手,但我想知道这是否可能:我想检查一个目录是否有带有文件名后缀的文件.bam
,并且有数百个目录需要检查。我真的不想手动执行此操作,因此是否可以检查所有这些目录然后输出没有此类文件的列表?
答案1
在zsh
:
if ()(($#)) **/*.bam(ND.Y1)); then
print There is at least one regular file in here whose name ends in .bam
fi
directories_without_bam=(
**/*(ND/^e['()(($#)) $REPLY/*.bam(ND.Y1)'])
)
if (( $#directories_without_bam )); then
print "Directories without bam files:"
printf ' - %s\n' $directories_without_bam
fi
请注意,它不会查看当前工作目录 ( .
) 本身,只会查看在其下找到的目录。更改**/*
为{.,**/*}
还要考虑.
)。
答案2
使用bash
shell,您可以测试当前目录是否包含任何以 结尾的名称.bam
,如果不包含则打印一条消息,如下所示:
shopt -s dotglob nullglob
set -- ./*.bam
[ "$#" = 0 ] && echo 'nothing found'
shelldotglob
选项允许*
匹配隐藏名称,nullglob
如果不匹配任何内容,shell 选项将删除模式(而不是保持模式不变)。
我们set
可以扩展模式并将位置参数列表设置为匹配的名称。如果$#
位置参数列表的长度为零,则没有与该模式匹配的名称。
我们可以find
将这段代码应用于当前目录以及当前目录下的所有目录:
find . -type d -exec bash -O dotglob -O nullglob -c '
for d do
set -- "$d"/*.bam
[ "$#" = 0 ] && printf "%s\n" "$d"
done' bash {} +
这将从 开始递归地查找所有目录,.
并将它们批量提供给给定的内联bash
脚本。该脚本迭代给定的目录路径,并set
依次应用命令和测试,打印未生成匹配名称的目录的路径名。
shell 还有一个failglob
shell 选项,当模式与任何内容都不匹配时,该选项会生成失败。我们可以使用它来使代码变得更短(很小!)一点,但也可以说更难以阅读:
find . -type d -exec bash -O dotglob -O failglob -c '
for d do
(set -- "$d"/*.bam) 2>/dev/null || printf "%s\n" "$d"
done' bash {} +
答案3
与 @waltinator 的comm
实用理念类似,grep
可用于从其标准输入中删除一组字符串。
$ find mypath/ -type d |
grep -Fvxf <(find mypath/ -name \*.bam -type f -exec dirname {} \; | sort | uniq)
为了解释语法,管道的左侧创建了 下所有目录的列表mypath/
。注意右侧的括号。就像数学一样,这部分首先完成。 find
找到*.bam
下面的所有文件mypath/
,但仅打印每个文件的目录路径。然后对该输出进行sort
ed(可能不必要,但除了可能花费很少的时间之外不会造成任何损害),并uniq
进行 ed 以便每个目录名称仅出现一次。 inguniq
是对 的礼貌grep
,以防止它多次搜索相同的目录名。一旦grep
有了要删除的目录列表,它就会*.bam
从其输入流(所有目录的主列表)中删除由括号内的命令替换(文件位置列表)生成的每个目录。剩余的输出是不包含文件的目录集*.bam
。
答案4
正如 @waltinator 在评论中所说,您可以使用 find 命令:
find /your/path -type d '!' -exec sh -c 'ls -1 "{}" | egrep -i -q "^.*\.bam$"' ';' -print
可以找到解释这里。
样本输出:
$ find /usr/libexec -type d '!' -exec sh -c 'ls -1 "{}"|egrep -i -q "^.*\.so$"' ';' -print
/usr/libexec
/usr/libexec/emacs
/usr/libexec/emacs/29.1
/usr/libexec/emacs/29.1/x86_64-pc-linux-gnu
/usr/libexec/man-db
/usr/libexec/gcc
/usr/libexec/gcc/x86_64-pc-linux-gnu
/usr/libexec/gcc/x86_64-pc-linux-gnu/13/plugin
/usr/libexec/git-core
/usr/libexec/git-core/mergetools
/usr/libexec/podman
/usr/libexec/nullmailer