如何查找仅包含特定文件的目录

如何查找仅包含特定文件的目录

我有几个目录,其中包含无用的文件(例如*.tmp,,,,)。desktop.iniThumbs.db.picasa.ini

如何扫描所有驱动器以查找仅包含其中一些文件的目录?

答案1

要查找除 、 、 和/或 之外不包含其他名称*.tmpdesktop.ini所有Thumbs.db目录.picasa.ini

find . -type d -exec bash -O dotglob -c '
    for dirpath do
        ok=true
        seen_files=false
        set -- "$dirpath"/*
        for name do
            [ -d "$name" ] && continue  # skip dirs
            seen_files=true
            case "${name##*/}" in
                *.tmp|desktop.ini|Thumbs.db|.picasa.ini) ;; # do nothing
                *) ok=false; break
            esac
        done

        "$seen_files" && "$ok" && printf "%s\n" "$dirpath"
    done' bash {} +

这将用于find定位当前目录(包括当前目录)下的任何目录并将它们传递给 shell 脚本。

shell 脚本迭代给定的目录路径,并且对于每个目录路径,它都会*在其中展开(dotglob设置 shell 选项bash以捕获隐藏名称)。

然后,它会遍历结果名称列表,并将它们与我们想要查找的特定模式和名称进行匹配(忽略目录)。如果发现任何其他如果 name 与我们的列表不匹配,它会设置okfalse(从 has was true)并跳出该内部循环。

一旦我们看到除以下类型之外的任何类型的文件,该seen_files变量就会变为true目录(或者目录的符号链接)。该变量帮助我们避免报告仅包含其他子目录的子目录。

然后它运行$seen_filesand $ok(truefalse) 并且如果两者都是true,则意味着该目录至少包含一个常规文件,并且仅包含我们列表中的文件名,它打印目录的路径名。

代替

set -- "$dirpath"/*
for name do

你显然可以这样做

for name in "$dirpath"/*; do

反而。

测试:

$ tree
.
`-- dir
    |-- Thumbs.db
    `-- dir
        |-- file.tmp
        `-- something

2 directories, 3 files

find命令在此处运行,产生输出...)

./dir

这意味着该目录./dir仅包含列表中的名称(忽略目录),同时./dir/dir还包含其他内容。

[ -d "$name" ] && continue如果从代码中删除,./dir则不会找到该目录,因为它包含dir不在我们列表中的名称 ( )。

答案2

使用 find、xargs、ls、sed、wc 和 awk 命令的组合,它正在工作:

find . -type f \( -iname "desktop.ini" -o -name "thumb.db" \)  -printf %h\\0 | xargs -0 -I "{}" sh -c 'printf "{}\t"; ls -l "{}" | sed -n "1!p" | wc -l' | awk '$2 == "1" {print $0}'

解释:

  • find .在当前目录中查找
  • -type f只查找文件
  • \( -iname "desktop.ini" -o -name "thumb.db" \)其中文件名是“desktop.ini”或“thumb.db”,不区分大小写
  • printf %h\\0打印文件名的前导目录 + ASCII NUL
  • xargs -0 -I "{}" sh -c 'printf "{}\t"; ls -l "{}"打印输出目录并ls -l在每个目录上执行
  • sed -n "1!p" | wc -l'排除ls -l包含总文件和目录的第一行,然后计算行数
  • awk '$2 == "1" {print $0}'如果只有 count 等于“1”则打印行

答案3

您需要指定文件或文件夹,最好按名称指定,例如:

find ${HOME} -type f -iname thumbs.db -print0 | xargs -0 --no-run-if-empty rm

将找到所有-type f名为 ( ) -iname“thumbs.db”的文件 ( )(由于iin忽略大小写iname),然后删除 ( rm) 它们。

您可以使用文件名模式,例如

find ${HOME} -type f -iname '*.tmp' -print0 | xargs -0 --no-run-if-empty rm

警告:请小心您输入的内容,删除可能会在没有询问您的情况下发生。

请定期进行备份 - 在开始清理工作之前可能是一个好时机!

如果您想了解会发生什么,请在rm执行任何操作之前先查看文件列表,例如:

find ${HOME} -type f -iname thumbs.db -print0 | xargs -0 --no-run-if-empty ls -l

答案4

使用 GNUfind和 GNU awk,您可以find报告所有文件并awk进行匹配:

find . -depth -type d -printf '%p/\0' -o -printf '%p\0' |
  gawk -F/ -v OFS=/ -v RS='\0' -v IGNORECASE=1 '
    /\/$/ {
     NF--
     if (good[$0] == 0 && bad[$0] > 0) print
     next
    }
    {
      name = $NF
      NF--
      if (name ~ /^(.*\.tmp|desktop\.ini|Thumbs\.db|\.picasa\.ini)$/)
        bad[$0]++
      else
        good[$0]++
    }'

如果您还想包含空目录,请删除&& bad[$0] > 0.如果您想要区分大小写的匹配,请删除-v IGNORECASE=1.

相关内容