GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie parse ich die Ausgabe des Find-Befehls, wenn Dateinamen Leerzeichen enthalten?

Idealerweise machen Sie das gar nicht so, denn das korrekte Parsen von Dateinamen in einem Shell-Skript ist immer schwierig (korrigieren Sie es für Leerzeichen, Sie werden immer noch Probleme mit anderen eingebetteten Zeichen haben, insbesondere Zeilenumbruch). Dies wird sogar als erster Eintrag auf der BashPitfalls-Seite aufgeführt.

Allerdings gibt es eine Möglichkeit, fast das zu tun, was Sie wollen:

oIFS=$IFS
IFS=$'\n'

find . -name '*.txt' | while read -r i; do
  # use "$i" with whatever you're doing
done

IFS=$oIFS

Denken Sie daran, auch $i zu zitieren bei der Verwendung, um zu vermeiden, dass andere Dinge die Leerzeichen später interpretieren. Denken Sie auch daran, $IFS einzustellen zurück, nachdem Sie es verwendet haben, da dies nicht später zu verwirrenden Fehlern führen wird.

Dies hat eine weitere Einschränkung:was in while passiert -Schleife kann in einer Subshell stattfinden, abhängig von der genauen Shell, die Sie verwenden, sodass variable Einstellungen möglicherweise nicht bestehen bleiben. Die for Loop-Version vermeidet das aber um den Preis, auch wenn man den $IFS anwendet Lösung, um Probleme mit Leerzeichen zu vermeiden, dann bekommen Sie Probleme, wenn find gibt zu viele Dateien zurück.

Irgendwann besteht die richtige Lösung für all dies darin, es in einer Sprache wie Perl oder Python statt in der Shell zu tun.


Verwenden Sie find -print0 und leiten Sie es an xargs -0 weiter , oder schreiben Sie Ihr eigenes kleines C-Programm und leiten Sie es an Ihr kleines C-Programm weiter. Das ist was -print0 und -0 wurden erfunden für.

Shell-Skripte sind nicht der beste Weg, um Dateinamen mit Leerzeichen zu handhaben:Sie können es tun, aber es wird klobig.


Sie können den "internen Feldtrenner" (IFS ) zu etwas anderem als dem Leerzeichen für die Aufteilung der Schleifenargumente, z. B.

ORIGIFS=${IFS}
NL='
'
IFS=${NL}
for i in $(find . -name '*.txt'); do
    IFS=${ORIGIFS}
    #do stuff
done
IFS=${ORIGIFS}

Ich habe IFS zurückgesetzt nach seiner Verwendung in find, vor allem, weil es schön aussieht, denke ich. Ich habe keine Probleme darin gesehen, es auf Newline zu setzen, aber ich denke, das ist "sauberer".

Eine andere Methode, je nachdem, was Sie mit der Ausgabe von find machen möchten , ist entweder direkt -exec zu verwenden mit dem find Befehl oder verwenden Sie -print0 und leiten Sie es in xargs -0 . Im ersten Fall find kümmert sich um das Maskieren des Dateinamens. Im -print0 Fall, find druckt seine Ausgabe mit einem Nulltrennzeichen und dann xargs spaltet sich darüber auf. Da kein Dateiname dieses Zeichen enthalten kann (was ich weiß), ist dies auch immer sicher. Dies ist vor allem in einfachen Fällen sinnvoll; und ist normalerweise kein guter Ersatz für eine vollständige for Schleife.


Linux
  1. Wie weist man die Ausgabe eines Befehls einer Shell-Variablen zu?

  2. Wie stoppe ich den Find-Befehl nach dem ersten Match?

  3. Wie kann ich von der Befehlszeile aus feststellen, auf welcher Version von Os X ich mich befinde?

  4. Wie setze ich eine Variable gleich der Ausgabe eines Befehls in Grub2?

  5. So verwenden Sie den Linux-Befehl find zum Suchen von Dateien

So finden Sie Dateien in Linux mit dem Find-Befehl

So ändern Sie die Ausgabefarbe von „Echo“ in Linux

So finden Sie Dateien mit dem fd-Befehl in Linux

Wie man die CPU-Auslastung findet, was das System zum Hängen bringt

Was ist der Unterschied zwischen dem Befehl „locate“ und „find“ in Linux?

Wie kann die Ausgabe eines Befehls in eine Datei umgeleitet werden, wenn der Befehl Benutzereingaben auffordert?