find -exec の中でパイプを使って複数コマンドを実行する方法について説明します。
パイプを使った実行例
ここでは、カレントディレクトリ以下にあるファイルの中身を全て小文字にするコマンドを書くことを例に説明していきます。 一つのファイルだけであれば、次のコマンドでできます。
cat input.txt | tr 'A-Z' 'a-z' > input.txt.lower
これをそのまま、find -exec で実行しようとしても上手く動きません。
# 動かない例
find . -type f -name '*.txt' -exec cat {} | tr 'A-Z' 'a-z' > {}.lower \;
原因は -exec の後ろには1つのコマンドしか取れないからです。
find でパイプを使う方法
代わりに、sh -c "実行したいコマンド"
と書くことで複数のコマンドを一つのコマンドにまとめることで動くようになります。
find . -type f -name '*.txt' -exec sh -c "cat {} | tr 'A-Z' 'a-z' > {}.lower" \;
パイプの処理を関数に置き換える方法
もしシェルスクリプトを書いているなら、あえてワンライナーにする必要はないと思います。 複数のコマンドを一つのコマンドにまとめるという点で関数を使う方法があります。
tolower() {
cat "$1" | tr 'A-Z' 'a-z' > "$1".lower
}
find . -type f -name '*.txt' -exec tolower {} \;
findの結果をfor文で回す方法
その他に挙げるとすれば、-exec
を使わないで for-in
を使う方法もあります。
for file in $(find . -type f -name '*.txt'); do
cat "$file" | tr 'A-Z' 'a-z' > "$file".lower
done
以上です。