指定されたファイル名を持つファイルを含まないすべてのディレクトリのリスト

指定されたファイル名を持つファイルを含まないすべてのディレクトリのリスト

すべてのディレクトリをどのようにリストしますか?いいえ指定されたファイル名を持つファイルはありますか?たとえば、このツリーが与えられた場合

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

これを行うディレクトリを一覧表示したいと思います。いいえというファイルがありますREADMEが、この場合はディレクトリになります/c。どうすればいいですか?findたとえば、構文を考えることはできません。

答え1

findGNUなどの実装がパラメータの挿入を許可すると仮定するfindと、次のようになります。{}-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/

再帰が必要な場合は、次のものを使用できます(この場合はデフォルトでbashこれzshを行うことができます。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に通常のファイルがないかどうかはどうすればわかりますか?それはすべてです。

関連情報