特定のファイルにsedを適用し、変更されたファイルをリストして、変更されたファイルがわかるようにするスクリプトを書いています。
これは私がsedを見つけて使用する方法です:
find . -type f -a \( -name "*.txt" -o -name "*.git"\) -a -exec sed -i -e "s/"str1"/"str2"/g" {} +
変更されたファイルのファイル名を印刷するにはどうすればよいですか?読みやすくするために、並べ替えて印刷したいと思います。
Sedのみを使用する場合、これを行うことができます。
sed -i 's/$pattern/$new_pattern/w changelog.txt' $filename
if [ -s changelog.txt ]; then
# CHANGES MADE, DO SOME STUFF HERE
else
# NO CHANGES MADE, DO SOME OTHER STUFF HERE
fi
しかし、findとsedを一緒に使用する場合、どうすればよいですか? manページをチェックして、たくさんのことを試しましたが、何も機能しませんでした。
sed -i
は、s
スクリプトのsed
コマンドのいずれかが成功したかどうかに関係なく、ファイルを書き換えます(実際にはファイルの完全な新しいコピーを作成します)。
ここでは、sed -i
を含まないファイルでstr1
を実行することは避けたいと思います。 GNUツールを使用:
find . -type f \( -name "*.txt" -o -name "*.git" \) -size +3c \
-exec grep -lZ str1 {} + |
while IFS= read -rd '' file; do
sed -i 's/str1/str2/g' "$file" &&
printf '%s\n' "$file"
done
これは、str1
を含むファイルごとに1つのsed
を実行し、sed
が成功した場合(新しいバージョンの作成でエラーが発生しなかった場合)にファイル名を出力します。ファイル)。
または、ファイルごとに1つのgrep
とsed
を実行できます。
find . -type f \( -name "*.txt" -o -name "*.git" \) \( -size +3c \
-exec grep -q str1 {} \; \
-exec sed -i 's/str1/str2/g' {} \; \
-printf '"%p" was modified\n' \
-o -printf '"%p" was not modified\n"' \)
sed
コマンド(適切な引用符付き):
sed 's/str1/str2/g'
これにより、str1
のすべての出現箇所がstr2
に変更されます。 str1
を含むファイルのリストはgrep -l 'str1'
から取得できます。
find . -type f \( -name '*.txt' -o -name '*.git' \) \
-exec grep -l 'str1' {} \; \
-exec sed -i 's/str1/str2/g' {} + >changelist.txt
ここで、grep -l
は、changelist.txt
にリダイレクトされるパス名のリストを提供します。また、sed
のフィルターのように機能するため、sed
はパターンを含むファイルでのみ実行されます。 sed -i
はファイルに変更を加えます(そして静かなままです)。
または、find
に文字列を含むファイルのパス名を出力させます。
find . -type f \( -name '*.txt' -o -name '*.git' \) \
-exec grep -q 'str1' {} \; \
-print \
-exec sed -i 's/str1/str2/g' {} + >changelist.txt
関連:
必要なことを実行する小さなスクリプトを記述し、exec
への引数としてスクリプトをfind
書くのは簡単です。すでにスクリプトがあり、$filename
を$1
に置き換えると、スクリプトができます。スクリプトは次の形式になります
#!/bin/bash
sed -i 's/$pattern/$new_pattern/' $1
echo $1 >> changelog
このスクリプトをed_notify
と呼びましょう。これで、選択したファイルで実行できます。
cat changelog >> changelog.old
rm changelog
find . -type f -a \( -name "*.txt" -o -name "*.git"\) -a -exec ed_notify {} \;