Execを使用すると、すべてのパラメータを一度に渡す{} +
か、次を使用して1つずつ渡すことができます。{} \;
それでは、すべての名前を変更したいとしましょう。JPEG、これを行うには問題はありません。
find . \( -name '*.jpg' -o -name '*.jpeg' \) -exec mv '{}' '{}'.new \;
ただし、出力をリダイレクトする必要がある場合は、'{}'
リダイレクト後にアクセスできません。
find . \( -name '*.jpg' -o -name '*.jpeg' \) -exec cjpeg -quality 80 '{}' > optimized_'{}' \;
これはうまくいきません。 forループを使用してfindを使用する前に、出力を変数に保存する必要があります。現実を直視すると、それは面倒なことです。
for f in `find . \( -name '*.jpg' -o -name '*.jpeg' \)`; do cjpeg -quality 80 $f > optimized_$f; done;
それでは、より良い方法がありますか?
答え1
bash -c
コマンドで使用find -exec
し、bashコマンドで位置引数を使用できます。
find . \( -name '*.jpg' -o -name '*.jpeg' \) -exec bash -c 'cjpeg -quality 80 "$1" > "$(dirname "$1")/optimized_$(basename "$1")"' sh {} \;
{}
この方法が提供されます$1
。
sh
{}
ここで使用される文字列は、内部シェルに「名前」を通知する前のエラーメッセージに使用されます。これについては、以下でさらに詳しく説明します。stackoverflowに対するこの回答。
答え2
答えがあります(https://unix.stackexchange.com/a/481687/4778)、しかしそれが理由です。
リダイレクト>
、パイピング、|
および$
拡張はすべて、コマンドを実行する前にシェルで実行されます。したがって、optimized_{}
始める前にstdoutがにリダイレクトされます。find
答え3
現在のシェルがそれを解釈するのを防ぐには、リダイレクトが必要です。
ただし、これを引用すると、コマンドの出力がリダイレクトされるのを防ぐことができます。
既知の解決策はシェルを呼び出すことです。
find . -name '*.jpg' -exec sh -c 'echo "$1" >"$1".new' called_shell '{}' \;
この場合、リダイレクト(>
)は現在のシェルで参照され、呼び出しシェル内で正常に動作します。サブシェル()の引数(名前)として使用されますcalled_shell
。$0
sh
ファイル名にサフィックスを追加するとうまく機能しますが、プレフィックスを使用するとうまく機能しません。プレフィックスが機能するようにするには、./
ファイル名の前の検索を削除して${1#./}
その-execdir
オプションを使用する必要があります。
-iname
このオプションを使用して、*.JPG
名前が付けられたファイルや他のバリエーションのあるファイルも含めることも、そうでない場合もあります。*.JpG
find . \( -iname '*.jpg' -o -iname '*.jpeg' \) -execdir sh -c '
cjpeg -quality 80 "$1" > optimized_"${1#./}"
' called_shell '{}' \;
for f do … ; done
最後にループ()とaを追加して、ファイルごとに1回ではなく、ディレクトリごとに1回シェルを呼び出すことも、そうでない場合もあります。+
find . \( -iname '*.jpg' -o -iname '*.jpeg' \) -execdir sh -c '
for f; do cjpeg -quality 80 "$f" > optimized_"${f#./}"; done
' called_shell '{}' \+
最後に、cjpeg
ファイルに直接書き込むことができれば、リダイレクトは防止されます。
find . \( -iname '*.jpg' -o -iname '*.jpeg' \) -execdir sh -c '
for f; do cjpeg -quality 80 "$f" -outfile optimized_"${f#./}"; done
' called_shell '{}' \+
答え4
スクリプトcjq80を生成します。
#!/bin/bash
cjpeg -quality 80 "$1" > "${1%/*}"/optimized_"${1##*/}"
実行可能にする
chmod u+x cjq80
-execで使用してください。
find . \( -name '*.jpg' -o -name '*.jpeg' \) -exec cjq80 '{}' \;