
すべてのテキスト ファイルが改行文字で終わるようにするスクリプトを作成しようとしています。
特定のフォルダーでこのコマンドを実行すると、次のようになります。
find . -exec ed -s {} <<< w \;
次のような出力が得られます。
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
わかりました。では、改行が追加されたファイルはどれですか? Git 履歴には変更が見られないので、これらは追跡されていないファイルですか?
また、テキスト ファイルの 1 つの末尾から改行を意図的に削除し、ed
それを元に戻していません...
答え1
コマンドが少し間違っています。<<<
入力リダイレクト (here-string) がfind
ではなくに接続されているためですed
。
コマンドを少し拡張するには:
find . -type f -exec sh -c '
for pathname do
echo w | ed -s "$pathname"
done' sh {} +
これは、現在のディレクトリまたはその下にある通常のファイルにのみ影響し、 を使用したディレクトリやその他のファイルタイプを編集しようとはしませんed
。バイナリ ファイルも通常のファイルであるため、コンパイルされた実行ファイルやイメージ ファイルなどに損傷を与えないように、テキスト ファイルを含むディレクトリでのみこれを実行することを想定する必要があります。
通常のファイルのバッチの場合、これは短いインライン シェル スクリプトを呼び出します。スクリプトは によって指定されたパス名をループしfind
、 で各ファイルを開いてed
、ファイルを直ちに保存します。これにより、改行文字で終了していないファイルに改行が追加されます。
実際にどのファイルがこれによって変更されるかを知るには、 を呼び出す前にパス名を出力しますed
。これは次のように出力します。全てパス名は見つかりましたが、リストにはいくつかのパス名の後に「改行が追加されました」というメッセージが散在していました。
find . -type f -exec sh -c '
for pathname do
printf "%s\n" "$pathname"
echo w | ed -s "$pathname"
done' sh {} +
これによって実際に変更されたファイルを検出するには、一時ファイルに書き込み、それを元のファイルと比較し、違いがある場合は元のファイルを一時ファイルに置き換えます。
find . -type f -exec sh -c '
tmpfile=$(mktemp); trap "rm -f \"$tmpfile\"" EXIT
for pathname do
printf "w %s\n" "$tmpfile" | ed -s "$pathname" 2>/dev/null
if ! cmp -s "$tmpfile" "$pathname"; then
printf "Fixed %s\n" "$pathname"
mv "$tmpfile" "$pathname"
fi
done' sh {} +
これには、実際に変更したファイル以外のファイルのタイムスタンプが更新されないという追加の利点があります。
これにより、「改行が追加されました」というメッセージも抑制されed
、代わりにファイルが実際に変更されるたびにカスタム メッセージが出力されます。
参照: