如何查找某些文件存在但其他文件不存在的目录

如何查找某些文件存在但其他文件不存在的目录

假设我有很多报告目录,并且report.md在包含报告的目录中总是有一个文件,但report.pdf仅在已完成的报告中。我想找到report.md存在但没有report.pdf.

reports_dir
|
+-- project_xyz
|   +-- report.md
|   +-- image.png
|
+-- bugs
|   +-- report.md
|   +-- report.pdf
|   +-- Makefile
|
+-- homework
    +-- report.pdf
    +-- test.md

如果我将此函数用作search "reports_dir" --include "report.md" --exclude "report.pdf",它应该返回/project_xyz,但不会/bugs返回/homework

sh在/中进行此类搜索的最快方法是什么bash? (单行优先)

答案1

for f in "$1"/*/"$2"; do dir=$(dirname -- "$f"); [ -f "$dir/$3" ] || printf '%s\n' "$dir"; done

将脚本另存为search.第一个参数是父目录,第二个参数是包含目录,第三个参数是排除目录。

sh search "reports_dir" "report.md" "report.pdf"
  • "$1"/*/"$2"report.md仅获取示例中文件的路径。

  • dir=$(dirname -- "$f")获取这些文件的目录路径(假设它不以换行符结尾)。

  • [ -f "$dir/$3" ]测试该目录 ( ) 中第三个参数中的文件是否存在,report.pdf这就是常规的类型(不是目录、fifo、设备...)。

  • || printf '%s\n' "$dir"如果它不存在(或者不是常规的文件),打印目录名称。

答案2

zsh

print -rC1 -- **/report.md(DN^e['[[ -e $REPLY:r.pdf ]]']:h)

print raw on 1 Column任何级别的子目录 ( ) 下的文件h的 ead (dirname),包括ot (隐藏)文件,对于这些子目录,代码的评估不会 ( ) 返回 true (其中包含文件的 oot 名称在哪里)查看)。report.md**/De[[ -e $REPLY:r.pdf ]]^$REPLY:rr$REPLY

通过允许嵌入参数和任何类似 Bourne 的 shell(包括)的find实现(例如 GNU ) ,您可以执行以下操作:find{}-execbash

find . -type d -exec test -e '{}/report.md' \; \
             ! -exec test -e '{}/report.pdf' \; -print

但这意味着每个目录最多执行 2 个test命令。

通过boshfind内置功能,可以通过以下方式避免这种情况:

find . -type d -call '
  [ -e "$1/report.md" ] && [ ! -e "$1/report.pdf" ]' {} \; -print

这次,-callshell 直接解释该代码并调用内置的[.

POSIXly:

find . -type d -exec sh -c '
  for d do
    [ ! -e "$d/report.md" ] || [ -e "$d/report.pdf" ] || printf "%s\n" "$d"
  done' sh {} +

对于那些内置的sh实现(现在大多数),应该相对有效,因为调用它来处理它找到的目录列表的次数尽可能少。[printfshfind

答案3

您可以使用简短的 bash 单行语句来测试 PDF 是否存在(-exec也是一个过滤器):

find . -name '*.md' -exec bash -c '[[ -f "${1%.*}.pdf" ]] && exit 1; exit 0;' bash-line {} \; -print

如果您只需要目录名称,您也可以将其放在-exec第一个目录之后的另一个目录中(find在第一个测试后停止):

find . -name '*.md' -exec bash -c '[[ -f "${1%.*}.pdf" ]] && exit 1; exit 0;' bash-line {} \; -exec dirname {} \;

答案4

也许这会起作用?

comm -23 <(find -name "report.md" -printf '%h\n' | sort) <(find -name "report.pdf" -printf '%h\n' | sort)

相关内容