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 -execohnesh -cscheint ohne Probleme zu funktionieren – hier kein Zitieren nötig:[email protected] ~ % find findtest -type f -exec cat {} ; one two three -
Aber wenn ich
sh -cverwende{}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 > {}'