Ich versuche, find
zu verwenden zu echo 0
in einige Dateien, aber anscheinend funktioniert das nur mit sh -c
:
find /proc/sys/net/ipv6 -name accept_ra -exec sh -c 'echo 0 > {}' ;
Aber mit sh -c
mit find -exec
macht mich sehr unruhig, weil ich Zitierprobleme vermute. Ich habe ein wenig daran herumgefummelt und anscheinend war mein Verdacht berechtigt:
-
Mein Testaufbau:
[email protected] ~ % cd findtest [email protected] ~/findtest % echo one > file with spaces [email protected] ~/findtest % echo two > file with 'single quotes' [email protected] ~/findtest % echo three > file with "double quotes" [email protected] ~/findtest % ll insgesamt 12K -rw-rw-r-- 1 martin martin 6 Sep 17 12:01 file with "double quotes" -rw-rw-r-- 1 martin martin 4 Sep 17 12:01 file with 'single quotes' -rw-rw-r-- 1 martin martin 4 Sep 17 12:01 file with spaces
-
Verwenden von
find -exec
ohnesh -c
scheint ohne Probleme zu funktionieren – hier kein Zitieren nötig:[email protected] ~ % find findtest -type f -exec cat {} ; one two three
-
Aber wenn ich
sh -c
verwende{}
scheint eine Art Zitieren zu erfordern:[email protected] ~ % LANG=C find findtest -type f -exec sh -c 'cat {}' ; cat: findtest/file: No such file or directory cat: with: No such file or directory cat: spaces: No such file or directory cat: findtest/file: No such file or directory cat: with: No such file or directory cat: single quotes: No such file or directory cat: findtest/file: No such file or directory cat: with: No such file or directory cat: double quotes: No such file or directory
-
Doppelte Anführungszeichen funktionieren, solange kein Dateiname doppelte Anführungszeichen enthält:
[email protected] ~ % LANG=C find findtest -type f -exec sh -c 'cat "{}"' ; one two cat: findtest/file with double: No such file or directory cat: quotes: No such file or directory
-
Einfache Anführungszeichen funktionieren, solange kein Dateiname einfache Anführungszeichen enthält:
[email protected] ~ % LANG=C find findtest -type f -exec sh -c "cat '{}'" ; one cat: findtest/file with single: No such file or directory cat: quotes: No such file or directory three
Ich habe keine Lösung gefunden, die in allen Fällen funktioniert. Übersehe ich etwas oder verwende sh -c
in find -exec
von Natur aus unsicher?
Akzeptierte Antwort:
Betten Sie niemals {}
ein im Shell-Code! Dadurch entsteht eine Command-Injection-Schwachstelle. Beachten Sie das für cat "{}"
, es geht nicht nur um den "
Zeichen, ,
`
, $
sind ebenfalls ein Problem (man denke zum Beispiel an eine Datei namens ./$(reboot)/accept_ra
)¹.
Hier möchten Sie die Dateinamen als separate Argumente an sh
übergeben (nicht im Code -Argument) und sh
Inline-Skript (der code Argument), um mit Positionsparametern darauf zu verweisen:
find . -name accept_ra -exec sh -c 'echo 0 > "$1"' sh {} ;
Oder um zu vermeiden, dass ein sh
ausgeführt wird pro Datei:
find . -name accept_ra -exec sh -c 'for file do
echo 0 > "$file"; done' sh {} +
Dasselbe gilt für xargs -I{}
oder zsh
‘s zargs -I{}
. Schreiben Sie nicht:
<list.txt xargs -I{} sh -c 'cmd > {}'
Das wäre eine Command Injection Schwachstelle, genauso wie bei find
oben, aber:
<list.txt xargs sh -c 'for file do cmd > "$file"; done' sh
Das hat auch den Vorteil, dass ein einziges sh
nicht ausgeführt wird pro Datei und den Fehler bei list.txt
enthält keine Datei.
Mit zsh
‘s zargs
, möchten Sie wahrscheinlich eine Funktion verwenden, anstatt sh -c
aufzurufen :
do-it() cmd > $1
zargs ./*.txt -- do-it
Beachten Sie, dass in allen obigen Beispielen das zweite sh
oben geht in den $0
des Inline-Skripts . Sie sollten dort etwas Relevantes verwenden (wie sh
oder find-sh
), nicht Dinge wie _
, -
, --
oder die leere Zeichenfolge als Wert in $0
wird für die Fehlermeldungen der Shell verwendet:
$ find . -name accept_ra -exec sh -c 'echo 0 > "$1"' inline-sh {} ;
inline-sh: ./accept_ra: Permission denied
GNU parallel
funktioniert anders. Damit tun Sie nicht sh -c
verwenden möchten als parallel
führt bereits eine Shell aus und versucht, {}
zu ersetzen mit dem angegebenen Argument in der richtigen Syntax für die Shell.
<list.txt PARALLEL_SHELL=sh parallel 'cmd > {}'