列出所有不包含給定檔案名稱的檔案的目錄

列出所有不包含給定檔案名稱的檔案的目錄

我將如何列出所有目錄不是裡面有一個給定檔案名稱的檔案嗎?例如給定這棵樹

/
  /a
     README
     file001
     file002
  /b
     README
     file001
  /c
     file003

我想列出執行此操作的目錄不是有一個名為 的文件README,在本例中它將是目錄/c。我該怎麼做呢?我想不出任何使用例如的語法find

答案1

假設find像 GNUfind這樣的實作接受{}嵌入在參數中-exec

$ find . -type d \! -exec test -e '{}/README' \; -print

或者,沒有有問題的嵌入:

$ find . -type d ! -exec sh -c 'test -e "$1"/README' sh {} \; -print

例子

這裡目錄 1/1 到 5/5 有 README,其他目錄是空的。

$ tree 
.
|-- 1
|   `-- 1
|       `-- README
|-- 10
|   `-- 10
|-- 2
|   `-- 2
|       `-- README
|-- 3
|   `-- 3
|       `-- README
|-- 4
|   `-- 4
|       `-- README
|-- 5
|   `-- 5
|       `-- README
|-- 6
|   `-- 6
|-- 7
|   `-- 7
|-- 8
|   `-- 8
`-- 9
    `-- 9

現在,當我們運行此版本的find命令時:

$ find . -type d \! -exec test -e '{}/README' \; -print
.
./10
./10/10
./7
./7/7
./9
./9/9
./6
./6/6
./5
./8
./8/8
./4
./1
./3
./2

參考

答案2

不需要find。只需使用外殼:

for d in */; do [ -f "$d"README ] || printf '%s\n' "$d"; done
c/

如果需要遞歸,可以使用(對於bashzsh預設可以這樣做,set -o globstar在 中使用ksh93):

shopt -s globstar
for d in **/; do [ -f "$d"README ] || printf '%s\n' "$d"; done

(請注意,預設排除點文件)。

答案3

您可以使用-exec選項來find檢查文件,然後列印檢查失敗的所有結果。

find /path/to/base -mindepth 1 -maxdepth 1 -type d -exec test -e {}/README \; -o -print

答案4

便攜地,你可以這樣做:

find . -type d -exec sh -c '
  for dir do
    [ -f "$dir/README" ] || printf "%s\n" "$dir"
  done' sh '{}' +

[ -f file ]測試文件是否存在 被確認為常規文件(符號連結解析後)。

如果您想測試它是否僅存在(作為該目錄中的條目),無論其類型如何,您都需要:[ -e file ] || [ -L file ],但請注意,您需要對該目錄的搜尋權限才能執行這些測試。您可能需要添加一些[ -x "$dir" ]測試來解釋這些情況,例如:

find . -type d -exec sh -c '
  for dir do
    if [ -x "$dir" ]; then
      [ -f "$dir/README" ] || printf "%s\n" "$dir"
    else
      printf >&2 "Cannot tell for \"%s\"\n" "$dir"
    fi
  done' sh '{}' +

或者為了避免競爭條件,使用zsh

find . -type d -exec zsh -c '
  zmodload zsh/system
  for dir do
    ERRNO=0
    if [ ! -f "$dir/README" ]; then
      if [ "$errnos[ERRNO]" = ENOENT ]; then
        printf "%s\n" "$dir"
      else
        syserror -p "ERROR: $dir/README: "
      fi
    fi
  done' zsh '{}' +

也可以看看如何判斷 Bash 中是否不存在常規文件?就這樣。

相關內容