findコマンドの-execで2つのbashコマンドを使用するにはどうすればよいですか?


32

コマンドの-exec一部で2つのコマンドを使用することは可能findですか?

私は次のようなものを試しました:

find . -name "*" -exec  chgrp -v new_group {}  ; chmod -v 770 {}  \;

そして私は得る:

find:-execの引数が
ありませんchmod:アクセスできません{}:そのようなファイルまたはディレクトリはありません
chmod:アクセスできません;:そのようなファイルまたはディレクトリはありません

回答:


44

findコマンドについては、さらに-execコマンドを続けて追加することもできます。

find . -name "*" -exec chgrp -v new_group '{}' \; -exec chmod -v 770 '{}' \;

このコマンドは、結果として、以下を使用するのと同等です。

chgrp -v new_groupファイル&& chmod -v 770ファイル

各ファイルに。

すべてfindなどのパラメータ-name-exec-sizeなどは、実際にテストfindロングチェーン全体がこれまでに評価されているようにようにそれらを一つずつ実行していきます。そのため、連続した各-execコマンドは、前のコマンドがtrue(コマンドの終了ステータス)を返した場合のみ実行されます。しかし、また、論理演算子のような理解()とされていません()。したがって、以前の結果に関係なく一連のテストを使用するには、次のようなものを使用する必要があります。0find-o!-exec

find . -name "*" \( -exec chgrp -v new_group {} \; -o -exec chmod -v 770 {} \; \)

4
+1:はい、それが最もエレガントな方法です。理由を説明できる場合'{}'は、中括弧の周りにアポストロフィを使用してください。unix.stackexchange.com
ユーザー不明

1
@user残念ながら、それがまだ必要かどうかはわかりません。私は今いくつかのテストを行ったが、それが何かを変えるような状況に出くわしたことはない。消滅するのは単なる「良い習慣」だと思います。
rozcietrzewiacz

2
引用符は、名前にスペースが含まれるファイルにとって重要です。
-naught101

17
find . -name "*" -exec sh -c 'chgrp -v new_group "$0" ; chmod -v 770 "$0"' {} \;

@Gilles:の-c$ 0の奇妙な処理の不思議さは、私が一見するたびにこれが間違っていると思うようにしていますが、間違いなく正しいです。
-derobert

定義されている明示的なシェルが好きです
...-djangofan

この回答(およびGilesの回答)は、与えられた質問に対するより良い回答のようsh -cです。

14

コマンドは最初にシェルによって解析され、;改行で区切られたa で区切られた2つのコマンドになります。

find . -name "*" -exec chgrp -v new_group {}
chmod -v 770 {} \;

シェルコマンドを実行する場合は、明示的にシェルを呼び出しますbash -c(またはsh -c、シェルが特にbashであることを気にしない場合)。

find . -name "*" -exec sh -c 'chgrp -v new_group "$0"; chmod -v 770 "$0"' {} \;

{}シェルへの引数としての使用に注意してください。これは0番目の引数(通常はシェルまたはスクリプトの名前ですが、ここでは関係ありません)であるため、と呼ばれ"$0"ます。

一度に複数のファイル名をシェルに渡して、シェルでそれらを反復処理することができます。これにより高速になります。ここでは_、スクリプト名として渡し、次の引数はファイル名です(これfor xはのショートカットfor x in "$@")が繰り返されます。

find . -name "*" -exec sh -c 'for x; do chgrp -v new_group "$x"; chmod -v 770 "$x"; done' _ {} +

bash 4以降、またはzshでは、ここで見つける必要はまったくないことに注意してください。bashで、shopt -s globstar(ディレクトリに入れて~/.bashrc)実行**/して、再帰的なディレクトリglobの地位を有効にします。(zshでは、これは常にアクティブです。)その後

chgrp -v new_group -- **/*; chmod -v 770 -- **/*

または、ファイルを順番に繰り返したい場合

for x in **/*; do
  chgrp -v new_group -- "$x"
  chmod -v 770 -- "$x"
done

findコマンドとの1つの違いは、シェルがドットファイル(名前がで始まるファイル)を無視することです.。それらをbashに含めるには、最初に設定しGLOBIGNORE=.:..ます。zshでは**/*(D)、globパターンとして使用します。


この答え(およびグレンの答え)は、与えられた質問に対するより良い答えのようsh -cです。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.