Ich möchte Dateinamen an andere Programme weiterleiten, aber alle ersticken, wenn die Namen Leerzeichen enthalten.
Nehmen wir an, ich habe eine Datei namens.
foo bar
Wie kann ich find
den richtigen Namen zurückgeben?
Natürlich möchte ich:
foo\ bar
oder:
"foo bar"
EDIT : Ich möchte nicht durchgehen xargs
, ich möchte eine korrekt formatierte Zeichenfolge herausholen, find
damit ich die Zeichenfolge der Dateinamen direkt an ein anderes Programm weiterleiten kann.
-exec
Flagge mitfind
? Sie können diesen Fehler möglicherweise beheben und Ihren Befehl effizienter gestalten, indem-exec
Sie ihn nicht an andere Befehle weiterleiten. Nur meine $find
formatiert die Dateinamen gut; Es wird ein Name pro Zeile geschrieben. (Dies ist natürlich mehrdeutig, wenn ein Dateiname ein Zeilenvorschubzeichen enthält.) Das Problem ist also, dass das empfangende Ende "erstickt", wenn es ein Leerzeichen erhält. Dies bedeutet, dass Sie uns mitteilen müssen, was das empfangende Ende ist, wenn Sie eine aussagekräftige Antwort wünschen .find
eine Option zur Ausgabe von Dateinamen in einem für die Shell geeigneten Format angeboten würde. Im Allgemeinen funktioniert die-print0
GNU-find
Erweiterung jedoch auch in vielen anderen Szenarien, und Sie sollten auf jeden Fall lernen, sie zu verwenden.ls $(command...)
füttert die Liste nicht durchstdin
. Es setzt die Ausgabe von$(command...)
direkt in die Befehlszeile. In diesem Fall liest die Shell aus c und verwendet den aktuellen Wert von$IFS
, um zu entscheiden, wie die Ausgabe in Wörter aufgeteilt wird. Im Allgemeinen ist es besser, wenn Sie verwendenxargs
. Sie werden keinen Leistungstreffer bemerken.find -printf '"%p"\n'
fügt jeden gefundenen Namen in doppelte Anführungszeichen ein, fügt jedoch keine doppelten Anführungszeichen in einen Dateinamen ein. Wenn Ihre Dateinamen keine Anführungszeichen enthalten, können Sie das Problem ignorieren: oder durchleitensed 's/"/&&/g;s/^""/"/;s/""$/"/'
. Wenn Ihre Dateinamen von der Shell verarbeitet werden, sollten Sie wahrscheinlich einfache Anführungszeichen anstelle von doppelten Anführungszeichen verwenden (andernfallssweet$HOME
wird dies zu etwas ähnlichemsheet/home/you
). Und dies ist immer noch nicht sehr robust gegenüber Dateinamen mit Zeilenumbrüchen. Wie wollen Sie damit umgehen?Antworten:
POSIXLY:
Mit
find
Unterstützungen-print0
undxargs
Unterstützungen-0
:-0
Die Option weist xargs an, das ASCII-NUL-Zeichen anstelle des Leerzeichens zu verwenden, um die Dateinamen zu beenden (zu trennen).Beispiel:
quelle
ls $(find . -maxdepth 1 -type f -print0 | xargs -0)
bekomme ichls: cannot access ./foo: No such file or directory
ls: cannot access bar: No such file or directory
$(..)
in doppelte Anführungszeichen zu setzen"$(..)"
find
undxargs
.Mit
-print0
ist eine Option, aber nicht alle Programme unterstützen Nullbyte-getrennte Datenströme verwenden, so dass Sie verwenden müssen , werdenxargs
mit der-0
für einige Dinge Option, wie Gnouc Antwort zur Kenntnis genommen.Eine Alternative wäre,
find
's-exec
oder-execdir
Optionen zu verwenden. Der erste der folgenden Befehle füttert die Dateinamensomecommand
nacheinander, während der zweite eine Liste von Dateien enthält:Möglicherweise ist es in vielen Fällen besser, Globbing zu verwenden. Wenn Sie eine moderne Shell haben (bash 4+, zsh, ksh), können Sie rekursives Globbing mit
globstar
(**
) erhalten. In der Bash musst du folgendes einstellen:shopt -s globstar extglob
In meinem .bashrc steht eine Zeile, die besagt, dass dies für mich immer aktiviert ist (und erweiterte Globs, die auch nützlich sind).Wenn Sie keine Rekursivität wünschen, verwenden Sie
./*.txt
stattdessen einfach jeden * .txt im Arbeitsverzeichnis.find
Es verfügt über einige sehr nützliche, fein abgestimmte Suchfunktionen und ist für Zehntausende von Dateien obligatorisch (an diesem Punkt stoßen Sie auf die maximale Anzahl von Argumenten der Shell). Für die tägliche Verwendung ist dies jedoch häufig nicht erforderlich.quelle
Persönlich würde ich die Suchaktion verwenden
-exec
, um diese Art von Problem zu lösen. Oder, falls erforderlich,xargs
was eine parallele Ausführung ermöglicht.Es gibt jedoch eine Möglichkeit
find
, eine bash-lesbare Liste von Dateinamen zu erstellen. Es überrascht nicht, dass es-exec
undbash
insbesondere eine Erweiterung desprintf
Befehls verwendet:Während dies jedoch korrekt mit Shell-Escape-Zeichen versehene Wörter ausgibt, kann es nicht mit Shell-Escape-Zeichen verwendet werden
$(...)
, da$(...)
Anführungszeichen oder Escape-Zeichen nicht interpretiert werden. (Das Ergebnis von$(...)
unterliegt der Wortteilung und der Pfadnamenerweiterung, sofern es nicht in Anführungszeichen gesetzt ist.) Folgendes wird also nicht das tun, was Sie wollen:Was Sie tun müssten, ist:
(Beachten Sie, dass ich keinen wirklichen Versuch unternommen habe, die obige Monstrosität zu testen.)
Aber dann können Sie auch Folgendes tun:
quelle
ls
Szenario den Anwendungsfall des OP angemessen erfasst, aber dies ist nur eine Spekulation, da uns nicht gezeigt wurde, was er tatsächlich erreichen möchte. Diese Lösung funktioniert tatsächlich sehr gut; Ich erhalte die (vage) erwartete Ausgabe für alle lustigen Dateinamen, die ich ausprobiert habe, einschließlichtouch "$(tr a-z '\001-\026' <<<'the quick brown fox jumped over the lazy dogs')"
eval
besteht darin, dass Sie sie noch nicht übergeben müsseneval
. Sie können es in einem Parameter speichern und später verwenden, möglicherweise mehrmals mit verschiedenen Befehlen. OP gibt jedoch keinen Hinweis darauf, dass dies der Anwendungsfall ist (und wenn dies der Fall ist, ist es möglicherweise besser, die Dateinamen in ein Arrayerhalten Sie die Dateien und Verzeichnisse enthält Leerzeichen
erhalten Sie die Dateien enthält Leerzeichen
erhalten Sie die Verzeichnisse enthält Leerzeichen
quelle
quelle