web-dev-qa-db-ja.com

-execdirで検索

find-execdirで実行すると、期待した結果が得られません。

例えば:

mkdir -p a/b/c
find . -type d -execdir touch foo \;
$ tree a
a
├── b
│   ├── c
│   └── foo
└── foo

ディレクトリcにはfooファイルが含まれていません。 findにアクセスして各ディレクトリでローカルに何かをするにはどうすればよいですか?

16

一致するすべてのファイル(つまり、すべてのディレクトリ)について、findはそれを含むディレクトリ(つまり、その親ディレクトリ)に切り替え、指定されたコマンドを実行します。コマンドは一致の名前を使用しないので、すべてのディレクトリに作用することは決してありません。この特定のディレクトリツリーについては、

(cd . && touch foo)        # because ./a matches
(cd ./a && touch foo)      # because ./a/b matches
(cd ./a/b && touch foo)    # because ./a/b/c matches

すべてのディレクトリにファイルを作成するには、_findの実装が引数内で-execを許可している限り、-execdirの代わりに{}を使用できます(ほとんどの場合、特に私はすべてのものです):

find . -type d -exec touch {}/foo +

POSIXの移植性のために、ディレクトリ名とファイルベース名を手動でアセンブルする必要があります。

find . -type d -exec sh -c 'touch "$0/foo"' {} \;

または(少し速い)

find . -type d -exec sh -c 'for d; do touch "$d/foo"; done' _ {} +

または、bashの再帰的なワイルドカードマッチングを使用できます。 (kshやzshの対応する機能とは異なり、findコマンドとは異なり)bashはディレクトリへのシンボリックリンクの下で再帰することに注意してください。

shopt -s globstar
for d in **/*/; do touch -- "$d/foo"; done

Zshソリューション:

touch ./**/(e\''REPLY+=foo'\')

コマンドは、一致したファイルを含むすべてのディレクトリで実行されます。 cにはディレクトリが含まれていないため、一致せず、そこで実行されません。

解決策は、次のようにディレクトリ名をexecdir引数に追加することです。

find . -type d -execdir touch {}/foo \;
3
Jenny D

man file

   -execdir command {} +
          Like  -exec,  but  the  specified  command is run from the subdirectory containing the matched file

一致するディレクトリcbディレクトリにあるため、execが実行されます。ディレクトリではなくファイルを探している場合は、期待どおりに機能します。

ディレクトリの完全なリストが提供されるため、ディレクトリをxargsに送信することで、希望どおりの結果を得ることができます。

2
Matt