Wie kann ich sehen, welche Dateien durch den Befehl „ed“ geändert wurden?

Wie kann ich sehen, welche Dateien durch den Befehl „ed“ geändert wurden?

Ich versuche, ein Skript zu schreiben, das sicherstellt, dass alle Textdateien mit einem Zeilenumbruchzeichen enden.

Wenn ich diesen Befehl in einem bestimmten Ordner ausführe:

find . -exec ed -s {} <<< w \;

Ich erhalte die folgende Ausgabe:

Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended

Ok, aber an welche Dateien wurden die Zeilenumbrüche angehängt? Ich kann im Git-Verlauf keine Änderungen sehen. Handelt es sich also um nicht verfolgte Dateien?

Ich habe auch absichtlich den Zeilenumbruch am Ende einer meiner Textdateien entfernt und edfüge ihn nicht wieder hinzu …

Antwort1

Ihr Befehl ist leicht falsch, ebenso wie <<<eine Eingabeumleitung (Here-String), die an findund nicht an angehängt ist ed.

Um Ihren Befehl etwas zu erweitern:

find . -type f -exec sh -c '
    for pathname do
        echo w | ed -s "$pathname"
    done' sh {} +

Dies würde nur normale Dateien im aktuellen Verzeichnis oder darunter betreffen und nicht versuchen, Verzeichnisse und andere Dateitypen mit zu bearbeiten ed. Beachten Sie, dass Binärdateien auch normale Dateien sind. Daher müssen wir davon ausgehen, dass Sie dies nur in Verzeichnissen ausführen, die Textdateien enthalten (um kompilierte ausführbare Dateien, Bilddateien usw. nicht zu beschädigen).

Bei Stapeln regulärer Dateien würde dies ein kurzes Inline-Shell-Skript aufrufen. Das Skript würde die ihm von gegebenen Pfadnamen durchlaufen findund jeden in öffnen ed, nur um die Datei sofort zu speichern. Dies fügt die neue Zeile zu Dateien hinzu, die nicht bereits mit einem Zeilenumbruchzeichen enden.

Um einen Hinweis darauf zu erhalten, welche Dateien tatsächlich dadurch geändert werden, drucken Sie den Pfadnamen aus, bevor Sie aufrufen ed. Dies würde ausgebenallePfadnamen wurden gefunden, aber die Liste wäre nach einigen davon mit der Meldung „Neue Zeile hinzugefügt“ durchsetzt.

find . -type f -exec sh -c '
    for pathname do
        printf "%s\n" "$pathname"
        echo w | ed -s "$pathname"
    done' sh {} +

Um festzustellen, welche Dateien dadurch tatsächlich geändert wurden, könnte man in eine temporäre Datei schreiben, diese mit der Originaldatei vergleichen und bei einem Unterschied das Original durch die temporäre Datei ersetzen.

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 {} +

Dies hat den zusätzlichen Vorteil, dass Sie die Zeitstempel nur für die Dateien aktualisieren, die Sie tatsächlich ändern.

Dadurch wird auch die Meldung „Neue Zeile hinzugefügt“ unterdrückt edund stattdessen eine benutzerdefinierte Meldung ausgegeben, wenn eine Datei tatsächlich geändert wurde.

Siehe auch:

verwandte Informationen