「ed」コマンドでどのファイルが変更されたかをどのように確認できますか?

「ed」コマンドでどのファイルが変更されたかをどのように確認できますか?

すべてのテキストファイルが改行文字で終わることを保証するスクリプトを作成しようとしています。

特定のフォルダでこのコマンドを実行すると、次のようになります。

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 履歴に変更は表示されません。追跡されていないファイルも同じですか?

また、意図的にテキストファイルの末尾から改行文字を削除してed再追加しませんでした。

答え1

<<<入力リダイレクト(ここでは文字列)が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 {} +

これのもう1つの利点は、実際には変更されたファイル以外のファイルのタイムスタンプを更新しないことです。

これにより、「改行の追加」メッセージも抑制さedれ、ファイルが実際に変更されたときにカスタムメッセージが出力されます。

また見なさい:

関連情報