Ich möchte abschließende Leerzeichen aus allen Dateien in einer rekursiven Verzeichnishierarchie entfernen. Ich benutze das:
find * -type f -exec sed 's/[ \t]*$//' -i {} \;
Dies funktioniert, entfernt jedoch auch abschließende "Leerzeichen" aus den gefundenen Binärdateien, was unerwünscht ist.
Wie find
vermeide ich, diesen Befehl für Binärdateien auszuführen?
file
denen die Daten überprüft werden können.Antworten:
Sie könnten versuchen, den Unix-
file
Befehl zu verwenden, um die Dateien zu identifizieren, die Sie nicht möchten, aber ich denke, es ist besser, wenn Sie explizit angeben, welche Dateien Sie treffen möchten, als diejenigen, die Sie nicht möchten.um zu vermeiden, dass Sie in Quellcodeverwaltungsdateien gelangen, möchten Sie vielleicht etwas Ähnliches
Abhängig von Ihrer Shell benötigen Sie möglicherweise einige der Backslashes oder auch nicht.
quelle
-i
Option . Es ist schwer, einen portablen Shell-Befehl zu schreiben, oder?Dies kann über die Befehlszeile erfolgen.
quelle
Die einfachste und portabelste Antwort lautet:
Ich erkläre unten, warum, wo ich auch zeige, wie man es nur mit der Befehlszeile macht, und wie man mit trans-ASCII-Textdateien wie ISO-8859-1 (Latin-1) und UTF-8 umgeht, die oft keine haben -ASCII Leerzeichen in ihnen.
Der Rest der Geschichte
Das Problem ist, dass find (1) weder den
-T
Dateitest-Operator unterstützt, noch Codierungen erkennt, wenn dies der Fall ist - was unbedingt erforderlich ist, um die UTF-8-Standard-Unicode-Codierung zu erkennen.Sie könnten die Dateinamenliste durch eine Ebene führen, die Binärdateien ausgibt. Zum Beispiel
Jetzt haben Sie jedoch Probleme mit Leerzeichen in Ihren Dateinamen. Daher müssen Sie dies mit Nullterminierung verspäten:
Eine andere Sache, die Sie tun könnten, ist nicht zu verwenden,
find
aberfind2perl
, da Perl-T
bereits versteht :Und wenn Sie möchten, dass Perl davon ausgeht, dass sich die Dateien in UTF-8 befinden, verwenden Sie
Sie können das resultierende Skript auch in einer Datei speichern und bearbeiten. Sie sollten wirklich wirklich nicht nur den
-T
Filetest auf einer alten Datei ausführen, sondern nur auf Dateien, die reine Dateien sind, wie zuerst von bestimmt-f
. Andernfalls riskieren Sie das Öffnen von Gerätespecials, das Blockieren von Fifos usw.Wenn Sie dies jedoch alles tun, können Sie sed (1) genauso gut überspringen . Zum einen ist es portabler, da die POSIX-Version von sed (1) dies nicht versteht
-i
, wohingegen alle Versionen von Perl dies tun. Die neueren Versionen von sed haben die sehr nützliche-i
Option von Perl liebevoll übernommen, bei der ti zum ersten Mal auftaucht.Dies gibt Ihnen auch die Möglichkeit, Ihren regulären Ausdruck zu korrigieren. Sie sollten wirklich ein Muster verwenden, das mit einem oder mehreren horizontalen Leerzeichen übereinstimmt, und nicht mit Null, da sonst unnötige Kopiervorgänge langsamer ablaufen. Dies ist das:
sollte sein
Um sed (1) zu verstehen, ist jedoch eine Nicht-POSIX-Erweiterung erforderlich, normalerweise entweder
-R
für System Ⅴ Unices wie Solaris oder Linux oder-E
für BSD wie OpenBSD oder MacOS. Ich vermute, dass es unter AIX unmöglich ist. Es ist leider einfacher, eine tragbare Shell zu schreiben als ein Skript für eine tragbare Shell, wissen Sie.Warnung an 0xA0
Obwohl dies die einzigen horizontalen Leerzeichen in ASCII sind, haben sowohl ISO-8859-1 als auch Unicode das Leerzeichen NO-BREAK am Codepunkt U + 00A0. Dies ist eines der beiden wichtigsten Nicht-ASCII-Zeichen, die in vielen Unicode-Corpora vorkommen, und ich habe in letzter Zeit viele Leute gesehen, die den regulären Code gebrochen haben, weil sie ihn vergessen haben.
Warum machst du das nicht einfach so:
Wenn Sie könnten UTF-8 - Dateien zu behandeln, hinzufügen
-CSD
, und wenn Sie Perl v5.10 oder höher ausgeführt wird , können Sie\h
für die horizontalen Leerzeichen und\R
für einen generischen Zeilenumbrüche, die beinhalten\r
,\n
,\r\n
,\f
,\cK
,\x{2028}
, und\x{2029}
:Dies funktioniert für alle UTF-8-Dateien, unabhängig von den Zeilenumbrüchen, und beseitigt nachfolgende horizontale Leerzeichen (Unicode-Zeicheneigenschaft
HorizSpace
), einschließlich des lästigen Leerzeichens NO-BREAK, das vor einem Unicode-Zeilenumbruch (einschließlich CRLF-Combos) am Ende jeder Zeile auftritt.Es ist auch viel portabler als die sed (1) -Version, da es nur eine Perl (1) -Implementierung gibt, aber viele sed (1).
Das Hauptproblem, von dem ich sehe, dass es dort verbleibt, ist find (1), da es auf einigen wirklich widersprüchlichen Systemen (Sie wissen, wer Sie sind, AIX und Solaris) die überkritische
-print0
Direktive nicht versteht . Wenn das Ihre Situation ist, sollten Sie einfach dasFile::Find
Modul von Perl direkt verwenden und keine anderen Unix-Dienstprogramme verwenden. Hier ist eine reine Perl-Version Ihres Codes, die sich auf nichts anderes stützt:Wenn Sie nur ASCII- oder ISO-8859-1-Textdateien verwenden, ist dies in Ordnung. Wenn Sie jedoch ASCII- oder UTF-8-Dateien verwenden, fügen Sie die Optionen im internen
-CSD
Aufruf von Perl hinzu.Wenn Sie alle drei Codierungen von ASCII, ISO-8859-1 und UTF-8 gemischt haben, dann befürchte ich, dass Sie ein anderes Problem haben. :( Sie müssen die Kodierung auf Dateibasis herausfinden, und es gibt nie einen guten Weg, das zu erraten.
Unicode-Leerzeichen
Für den Datensatz hat Unicode 26 verschiedene Whitespace-Zeichen. Sie können das Dienstprogramm unichars verwenden, um diese auszuspionieren . Es werden fast immer nur die ersten drei horizontalen Whitespace-Zeichen angezeigt:
quelle
GNU grep kann ziemlich gut erkennen, ob eine Datei binär ist oder nicht. Außer Solaris gibt es sicher noch andere Plattformen, auf denen GNU grep nicht standardmäßig installiert ist, aber wie bei Solaris können Sie es sicher installieren.
Wenn Sie in Solaris sind, dann würden Sie ersetzen
grep
mit/opt/csw/bin/ggrep
.Die
grep
Flags führen Folgendes aus:l
Listet nur Dateinamen für übereinstimmende Dateien auf,R
ist rekursiv,I
stimmt nur mit Textdateien überein (ignoriert Binärdateien) undP
ist für die Syntax von Perl-kompatiblen regulären Ausdrücken vorgesehen.Der Perl-Teil ändert die Datei direkt und löscht alle nachfolgenden Leerzeichen / Tabulatoren.
Zum Schluss: Wenn UTF8 ein Problem ist, sollte die Antwort von tchrist in Verbindung mit meiner ausreichend sein, vorausgesetzt, der von
grep
Ihnen erstellte Build wurde mit UTF8-Unterstützung erstellt (normalerweise versuchen Paketbetreuer jedoch, diese Art von Funktionalität bereitzustellen).quelle