检查多个目录中是否存在具有特定名称的文件

检查多个目录中是否存在具有特定名称的文件

我是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

使用bashshell,您可以测试当前目录是否包含任何以 结尾的名称.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 还有一个failglobshell 选项,当模式与任何内容都不匹配时,该选项会生成失败。我们可以使用它来使代码变得更短(很小!)一点,但也可以说更难以阅读:

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/,但仅打印每个文件的目录路径。然后对该输出进行sorted(可能不必要,但除了可能花费很少的时间之外不会造成任何损害),并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

相关内容