
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 ed
füge ihn nicht wieder hinzu …
Antwort1
Ihr Befehl ist leicht falsch, ebenso wie <<<
eine Eingabeumleitung (Here-String), die an find
und 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 find
und 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 ed
und stattdessen eine benutzerdefinierte Meldung ausgegeben, wenn eine Datei tatsächlich geändert wurde.
Siehe auch: