Ist es möglich, mit dem find
Befehl alle "nicht-binären" Dateien in einem Verzeichnis zu finden? Hier ist das Problem, das ich zu lösen versuche.
Ich habe ein Archiv mit Dateien von einem Windows-Benutzer erhalten. Dieses Archiv enthält Quellcode und Bilddateien. Unser Build-System spielt nicht gut mit Dateien, die Windows-Zeilenenden haben. Ich habe ein Kommandozeilenprogramm ( flip -u
), das die Zeilenenden zwischen * nix und windows wechselt. Also, ich würde gerne so etwas machen
find . -type f | xargs flip -u
Wenn dieser Befehl jedoch für eine Image-Datei oder eine andere binäre Mediendatei ausgeführt wird, wird die Datei beschädigt. Mir ist klar, dass ich damit eine Liste mit Dateierweiterungen und Filtern erstellen kann, aber ich möchte lieber etwas, das nicht darauf angewiesen ist, dass ich diese Liste auf dem neuesten Stand halte.
Gibt es eine Möglichkeit, alle nicht-binären Dateien in einem Verzeichnisbaum zu finden? Oder gibt es eine alternative Lösung, die ich in Betracht ziehen sollte?
file
Dienstprogramm irgendwo in Ihrem Skript / Pipeline zu identifizieren , ob die Datei Daten oder TextAntworten:
Ich würde
file
die Ausgabe verwenden und in grep oder awk umleiten, um Textdateien zu finden, dann nur den Dateinamen-Teil derfile
Ausgabe extrahieren und das in xargs umleiten.so etwas wie:
Beachten Sie, dass das grep nach "ASCII-Text" und nicht nach "Text" sucht - Sie möchten wahrscheinlich nicht mit Rich-Text-Dokumenten, Unicode-Textdateien usw. herumspielen.
Sie können auch
find
(oder was auch immer) verwenden, um eine Liste von Dateien zu erstellen, mit denen Sie Folgendes überprüfen könnenfile
:Das
-d'\n'
Argument für xargs veranlasst xargs, jede Eingabezeile als separates Argument zu behandeln, wodurch Dateinamen mit Leerzeichen und anderen problematischen Zeichen berücksichtigt werden. Das heißt, es ist eine Alternative,xargs -0
wenn die Eingabequelle keine durch NULL getrennte Ausgabe erzeugt oder erzeugen kann (wie z. B.find
die-print0
Option 's' ). Laut dem Changelog hat xargs im September 2005 die Option-d
/ erhalten--delimiter
, sollte also in keiner nicht-alten Linux-Distribution verfügbar sein (ich war mir nicht sicher, weshalb ich das überprüft habe - ich habe mich nur vage daran erinnert, dass es eine "aktuelle" Erweiterung war).Beachten Sie, dass ein Zeilenvorschub ein gültiges Zeichen in Dateinamen ist. Dies wird also unterbrochen, wenn Dateinamen Zeilenvorschübe enthalten. Für typische Unix-Benutzer ist dies pathologisch verrückt, aber es ist nicht ungewöhnlich, ob die Dateien von Mac- oder Windows-Computern stammen.
Beachten Sie auch, dass dies
file
nicht perfekt ist. Es ist sehr gut darin, den Datentyp in einer Datei zu erkennen, kann aber gelegentlich verwirrt werden.Ich habe in der Vergangenheit viele Variationen dieser Methode mit Erfolg angewendet.
quelle
file
wird diesEnglish text
nichtASCII text
auf meinem Solaris-System angezeigt , daher habe ich diesen Teil entsprechend geändert. Auch habe ichawk -F: '{print $1}'
mit dem Äquivalent ersetztcut -f1 -d:
.grep -I
Filter Binärdateientext
zu suchen sollte ausreichen. Dies wird auchfile
Beschreibungen wieASCII Java program text
oderHTML document text
oder aufnehmentroff or preprocessor input text
.ASCII text
zu vermeiden, dass RTFs durcheinander gebracht werden.Nein. An einer binären oder nicht-binären Datei ist nichts Besonderes. Sie können Heuristiken wie 'enthält nur Zeichen in 0x01–0x7F' verwenden, aber das ruft Textdateien mit Nicht-ASCII-Zeichen als Binärdateien und unglückliche Binärdateien als Textdateien auf.
Nun, wenn Sie das einmal ignoriert haben ...
zip-Dateien
Wenn es von Ihrem Windows-Benutzer als ZIP-Datei stammt, unterstützt das ZIP-Format das Markieren von Dateien als Binärdatei oder als Text im Archiv. Sie können die
-a
Option von unzip verwenden , um darauf zu achten und zu konvertieren. Im ersten Absatz erfahren Sie natürlich, warum dies möglicherweise keine gute Idee ist (das Zip-Programm hat möglicherweise bei der Erstellung des Archivs einen Fehler vermutet).zipinfo teilt Ihnen mit, welche Dateien in seiner zip-Datei-Liste binär (b) oder text (t) sind.
andere Dateien
Der Befehl file überprüft eine Datei und versucht, sie zu identifizieren. Insbesondere werden Sie wahrscheinlich die
-i
Option (Ausgabe-MIME-Typ) nützlich finden. konvertiere nur Dateien mit dem Typ text / *quelle
Eine allgemeine Lösung für nur Prozess nicht binäre Dateien in
bash
Verwendungfile -b --mime-encoding
:Ich kontaktierte den Autor des Datei - Dienstprogramm , und er hat einen geschickten
-00
Paramter in Version 5.26 (2016.04.16 freigegeben wird , wird zum Beispiel in der aktuellen Arch und Ubuntu 16.10) , den Druckfile\0result\0
für mehrere Dateien ihn zugeführten sofort, auf diese Weise Sie tun können z.B:(Der
awk
Teil besteht darin, jede Datei herauszufiltern, die nicht binär ist.ORS
Ist das Ausgabetrennzeichen.)Kann natürlich auch in einer Schleife verwendet werden:
Basierend auf diesem und dem vorherigen
bash
Skript habe ich ein kleines Skript zum Herausfiltern von Binärdateien erstellt, das die neue Methode unter Verwendung des-00
Parameters vonfile
in neueren Versionen verwendet und bei älteren Versionen auf die vorherige Methode zurückgreift:Oder hier ein POSIX-y, aber es erfordert Unterstützung für
sort -V
:quelle
Die akzeptierte Antwort hat nicht alle für mich gefunden. Hier ist ein Beispiel für die Verwendung von greps
-I
, um Binärdateien zu ignorieren und alle versteckten Dateien zu ignorieren ...Hier wird es in einer praktischen Anwendung eingesetzt: dos2unix
https://unix.stackexchange.com/a/365679/112190
quelle
Die Antwort von Cas ist gut, setzt aber vernünftige Dateinamen voraus . Insbesondere wird davon ausgegangen, dass Dateinamen keine Zeilenumbrüche enthalten.
Es gibt keinen guten Grund, diese Annahme hier zu treffen, da es ziemlich einfach (und meiner Meinung nach sogar sauberer) ist, diesen Fall auch richtig zu behandeln:
Der
find
Befehl verwendet nur von POSIX angegebene Funktionen . Das-exec
Ausführen von beliebigen Befehlen als boolesche Tests ist einfach, robust (behandelt ungerade Dateinamen korrekt) und portabler als-print0
.Tatsächlich werden alle Teile des Befehls mit Ausnahme von POSIX angegeben
flip
.Beachten Sie, dass
file
die Genauigkeit der zurückgegebenen Ergebnisse nicht garantiert wird. In der Praxis ist es jedoch sehr zuverlässig, in der Ausgabe nach "ASCII-Text" zu suchen.(Möglicherweise fehlen einige Textdateien, es ist jedoch sehr unwahrscheinlich, dass eine Binärdatei fälschlicherweise als "ASCII-Text" identifiziert und unkenntlich gemacht wird. Wir sind also vorsichtig.)
quelle
calls
ohne Argumente kann sehr langsam sein, z. B. für Videos, die Ihnen alles über die Codierung erzählen.-
.file
, es können mehrere Dateien als Argumente verwendet werden.find
Befehl./
jedem Dateinamen vorangestellt wird , der an den Shell-Befehl übergeben wird. (3) Die gleichzeitige Verwendunggrep
als Test für eine einzelnefile
Befehlsausgabe ist die einzige POSIX-Methode, die ich erkennen kann, um den korrekten Umgang mit Dateinamen zu gewährleisten, die möglicherweise Zeilenumbrüche enthalten.file
das--mime-encoding
Flag und das--
Trennzeichen unterstützt, was von POSIX nicht garantiert wird .Dies findet alle regulären Dateien (
-type f
) im aktuellen Verzeichnis (oder darunter), diegrep
für nicht leer und nicht binär gehalten werden.Es wird verwendet
grep -I
, um zwischen binären und nicht-binären Dateien zu unterscheiden. Das-I
Flag und veranlassengrep
das Beenden mit einem Beendigungsstatus ungleich Null, wenn festgestellt wird, dass eine Datei binär ist. Eine "binäre" Datei ist demnachgrep
eine Datei, die Zeichen außerhalb des druckbaren ASCII-Bereichs enthält.Die
-q
Option togrep
bewirkt, dass das Programm mit dem Status 0 beendet wird, wenn das angegebene Muster gefunden wird, ohne dass Daten gesendet werden. Das von uns verwendete Muster ist ein einzelner Punkt, der mit einem beliebigen Zeichen übereinstimmt.Wenn festgestellt wird, dass die Datei nicht binär ist und mindestens ein Zeichen enthält, wird der Name der Datei gedruckt.
Wenn Sie sich mutig fühlen, können Sie
flip -u
es auch anschließen:quelle
Versuche dies :
Wo das Argument
grep '[^ -~]'
heißt'[^<tab><space>-~]'
.Wenn Sie es in einer Shell-Befehlszeile eingeben, geben Sie vorher Ctrl+ ein . In einem Editor sollte es kein Problem geben.VTab
'[^<tab><space>-~]'
stimmt mit jedem Zeichen überein, das kein ASCII-Text ist (Zeilenumbrüche werden von ignoriertgrep
).-L
druckt nur den Dateinamen von Dateien, die nicht übereinstimmen-Z
gibt Dateinamen aus, die durch ein Nullzeichen (fürxargs -0
) getrennt sindquelle
grep -P
(sofern verfügbar)\t
verfügbar ist. Alternativ können Sie die Gebietsschema-Übersetzung verwenden, wenn die Shell dies unterstützt:$'\t'
(bash
andzsh
do).Alternative Lösung:
Der Befehl dos2unix konvertiert Zeilenenden von Windows CRLF nach Unix LF und überspringt automatisch Binärdateien. Ich wende es rekursiv an mit:
quelle
dos2unix
mehrere Dateinamen als Argument verwendet werden können, ist dies weitaus effizienterfind . -type f -exec dos2unix {} +
sudo find / (-type f -und -path '* / git / *' -iname 'README') -exec grep -liI '100644 \ | 100755' {} \; -exec Flip -u {} \;
i. (-Typ f -und -Pfad '* / git / *' -iname 'README'): Sucht nach Dateien in einem Pfad, der den Namen git und die Datei mit dem Namen README enthält. Wenn Sie einen bestimmten Ordner und Dateinamen kennen, ist die Suche hilfreich.
Der Befehl ii.-exec führt einen Befehl für den von find generierten Dateinamen aus
iii. \; Zeigt das Ende des Befehls an
iv. {} ist die Ausgabe des Datei- / Ordnernamens, der bei der vorherigen Suche gefunden wurde
v. Mehrere Befehle können anschließend ausgeführt werden. Durch Anhängen von -exec "command" \; wie mit -exec flip -u \;
vii.grep
Sie können dieses Testverzeichnis klonen und ausprobieren: https://github.com/alphaCTzo7G/stackexchange/tree/master/linux/findSolution204092017
Ausführlichere Antworten finden Sie hier: https://github.com/alphaCTzo7G/stackexchange/blob/master/linux/findSolution204092017/README.md
quelle