Gibt es keine Möglichkeit, Leerzeichen in der Backtick- (oder $ (...)) - Erweiterung zu schützen?
Nein, das gibt es nicht. Warum das?
Bash hat keine Möglichkeit zu wissen, was geschützt werden sollte und was nicht.
Es gibt keine Arrays in der Unix-Datei / Pipe. Es ist nur ein Bytestream. Der Befehl innerhalb von ``
oder $()
gibt einen Stream aus, der schluckt und als einzelne Zeichenfolge behandelt. In diesem Fall haben Sie nur zwei Möglichkeiten: Setzen Sie es in Anführungszeichen, um es als eine Zeichenfolge zu behalten, oder setzen Sie es nackt, damit die Bash es entsprechend dem konfigurierten Verhalten aufteilt.
Wenn Sie also ein Array definieren möchten, müssen Sie ein Byte-Format definieren, das ein Array enthält, und das ist, was Werkzeuge mögen xargs
und find
tun: Wenn Sie sie mit dem -0
Argument ausführen , arbeiten sie nach einem binären Array-Format, mit dem Elemente abgeschlossen werden das Null-Byte, das dem ansonsten undurchsichtigen Byte-Stream Semantik hinzufügt.
bash
Kann leider nicht so konfiguriert werden, dass Zeichenfolgen auf dem Null-Byte aufgeteilt werden. Vielen Dank an /unix//a/110108/17980, dass Sie uns das gezeigt haben zsh
.
xargs
Sie möchten, dass Ihr Befehl einmal ausgeführt wird, und Sie sagten, dies xargs -0 -n 10000
löst Ihr Problem. Wenn dies nicht der Fall ist, wird sichergestellt, dass Ihr Befehl mehr als einmal ausgeführt wird, wenn Sie mehr als 10000 Parameter haben.
Wenn Sie möchten, dass es nur einmal ausgeführt wird oder fehlschlägt, müssen Sie das -x
Argument und ein -n
Argument angeben, das größer als das -s
Argument ist (wirklich: groß genug, dass eine ganze Reihe von Argumenten mit der Länge Null plus dem Namen des Befehls nicht hineinpassen die -s
Größe). ( Mann Xargs , siehe Auszug weit unten)
Das System, auf dem ich mich gerade befinde, hat einen Stack, der auf ca. 8 Millionen beschränkt ist. Hier ist mein Limit:
$ printf '%s\0' -- {1..1302582} | xargs -x0n 2076858 -s 2076858 /bin/true
xargs: argument list too long
$ printf '%s\0' -- {1..1302581} | xargs -x0n 2076858 -s 2076858 /bin/true
(no output)
Bash
Wenn Sie keinen externen Befehl einbeziehen möchten, ist die while-read-Schleife, die ein Array speist, wie in /unix//a/110108/17980 gezeigt , die einzige Möglichkeit für die Bash, Dinge zu trennen das Null-Byte.
Die Idee, das Skript als Quelle ( . ... "$@" )
zu verwenden, um die Stapelgrößenbeschränkung zu umgehen, ist cool (ich habe es ausprobiert, es funktioniert!), Aber wahrscheinlich nicht wichtig für normale Situationen.
Die Verwendung eines speziellen fd für die Prozessleitung ist wichtig, wenn Sie etwas anderes von stdin lesen möchten, es sonst aber nicht benötigen.
Der einfachste "native" Weg für den täglichen Haushaltsbedarf:
files=()
while IFS= read -rd '' file; do
files+=("$file")
done <(find ... -print0)
myscriptornonscript "${files[@]}"
Wenn Sie möchten, dass Ihr Prozessbaum sauber und ansprechend aussieht, können Sie mit dieser Methode exec mynonscript "${files[@]}"
den Bash-Prozess aus dem Speicher entfernen und ihn durch den aufgerufenen Befehl ersetzen. xargs
bleibt immer im Speicher, während der aufgerufene Befehl ausgeführt wird, auch wenn der Befehl nur einmal ausgeführt wird.
Was gegen die native Bash-Methode spricht, ist Folgendes:
$ time { printf '%s\0' -- {1..1302581} | xargs -x0n 2076858 -s 2076858 /bin/true; }
real 0m2.014s
user 0m2.008s
sys 0m0.172s
$ time {
args=()
while IFS= read -rd '' arg; do
args+=( "$arg" )
done < <(printf '%s\0' -- $(echo {1..1302581}))
/bin/true "${args[@]}"
}
bash: /bin/true: Argument list too long
real 107m51.876s
user 107m38.532s
sys 0m7.940s
bash ist nicht für das Array-Handling optimiert.
Mann Xargs :
-n max-args
Verwenden Sie höchstens max-args-Argumente pro Befehlszeile. Es werden weniger als max-args-Argumente verwendet, wenn die Größe (siehe Option -s) überschritten wird, sofern die Option -x nicht angegeben ist. In diesem Fall wird xargs beendet.
-s max-Zeichen
Verwenden Sie höchstens Zeichen mit maximaler Zeichenanzahl pro Befehlszeile, einschließlich des Befehls und der Anfangsargumente sowie der abschließenden Nullen an den Enden der Argumentzeichenfolgen. Der größte zulässige Wert ist systemabhängig und wird als Argumentlängenbeschränkung für exec abzüglich der Größe Ihrer Umgebung abzüglich 2048 Byte Headroom berechnet. Wenn dieser Wert größer als 128 KB ist, wird 128 KB als Standardwert verwendet. Andernfalls ist der Standardwert das Maximum. 1 KB sind 1024 Byte.
-x
Beenden Sie, wenn die Größe (siehe Option -s) überschritten wird.
IFS="
, newline,"
). Muss das Skript jedoch über alle Dateinamen ausgeführt werden? Wenn nicht, können Sie das Skript für jede Datei mit find selbst ausführen.