Ich habe viele Textdateien in einem Verzeichnis und möchte die letzte Zeile jeder Datei im Verzeichnis entfernen.
Wie kann ich es tun?
text-processing
files
ThehalfarisedPheonix
quelle
quelle
Antworten:
Wenn Sie Zugriff auf haben
vim
, können Sie Folgendes verwenden:quelle
Sie können diesen netten Oneliner verwenden, wenn Sie GNU haben
sed
.Dadurch wird die letzte Zeile jeder nicht ausgeblendeten Datei im aktuellen Verzeichnis entfernt. Switch
-i
for GNUsed
bedeutet, an Ort und Stelle zu arbeiten, und'$ d'
befiehltsed
, die letzte Zeile zu löschen ($
bedeutet "Letzte" und "d
Löschen").quelle
-i
einen GNUism, also ist das strittig, aber ich würde meinen alten Bart verlieren, wenn ich nicht darauf hinweisen würde, dass einige ältere Versionen vonsed
es dir nicht erlauben, Leerzeichen zwischen den$
undd
(oder) zu setzen. im Allgemeinen zwischen dem Muster und dem Befehl).*(.)
Glob für reguläre Dateien verwenden, ich kenne keine anderen Shells.Die anderen Antworten haben alle Probleme, wenn das Verzeichnis etwas anderes als eine reguläre Datei oder eine Datei mit Leerzeichen / Zeilenumbrüchen im Dateinamen enthält. Folgendes funktioniert unabhängig davon:
find "$dir" -type f
: Finden Sie die Dateien im Verzeichnis$dir
-type f
welche sind reguläre Dateien;-exec
Führen Sie den Befehl für jede gefundene Datei aussed -i
: Bearbeiten Sie die Dateien an Ort und Stelle;'$d'
: lösche (d
) die letzte ($
) Zeile.'+'
: weist find an, weiterhin Argumente hinzuzufügensed
(etwas effizienter, als den Befehl für jede Datei einzeln auszuführen, dank @zwol).Wenn Sie in die Unterverzeichnisse absteigen wollen nicht, dann können Sie das Argument hinzufügen
-maxdepth 1
zufind
.quelle
find
dies effizienter geschriebenfind $dir -type f -exec sed -i '$d' '{}' '+'
.)-print0
ist nicht im vollen Befehl vorhanden, warum es in der Erklärung setzen?-depth 0
nicht (findutils 4.4.2), sollte es stattdessen sein-maxdepth 1
.-exec
.Wenn Sie GNU verwenden
sed -i '$d'
, müssen Sie die gesamte Datei lesen und eine Kopie davon ohne die letzte Zeile erstellen, während es viel effizienter wäre, die Datei nur an Ort und Stelle zu kürzen (zumindest bei großen Dateien).Mit GNU
truncate
können Sie:Wenn die Dateien relativ klein sind, ist dies wahrscheinlich weniger effizient, da mehrere Befehle pro Datei ausgeführt werden.
Beachten Sie, dass für Dateien, die zusätzliche Bytes nach dem letzten Zeilenumbruchzeichen (nach der letzten Zeile) oder, mit anderen Worten, eine nicht begrenzte letzte Zeile enthalten , je nach
tail
Implementierungtail -n 1
nur diese zusätzlichen Bytes (wie GNUtail
) zurückgegeben werden. oder die letzte (richtig begrenzte) Zeile und diese zusätzlichen Bytes.quelle
|wc -c
imtail
anruf? (oder a${#length}
)${#length}
würde nicht funktionieren, da Zeichen, nicht Bytes, gezählt werden, und$(...)
würde das abschließende Zeilenumbruchzeichen entfernen, so${#...}
dass es um eins versetzt wäre, selbst wenn alle Zeichen Einzelbytes wären.Ein portablerer Ansatz:
Ich glaube nicht, dass dies einer Erklärung bedarf ... außer vielleicht, dass dies in diesem Fall
d
dasselbe ist,$d
daed
standardmäßig die letzte Zeile ausgewählt wird.Dies sucht nicht rekursiv und verarbeitet keine versteckten Dateien (auch Dotfiles genannt).
Wenn Sie auch diese bearbeiten möchten, lesen Sie Wie Sie versteckte Dateien in einem Verzeichnis mit * abgleichen
quelle
[[]]
,[]
ist es vollständig POSIX-kompatibel. ([[ ... ]]
Ist ein Bashismus.)[[
kein Bashismus ist )POSIX-kompatibler Einzeiler für alle Dateien, die rekursiv im aktuellen Verzeichnis beginnen, einschließlich Punktdateien:
.txt
Nur für Dateien, nicht rekursiv:Siehe auch:
quelle