Estoy tratando de usar find
a echo 0
en algunos archivos, pero aparentemente esto solo funciona con sh -c
:
find /proc/sys/net/ipv6 -name accept_ra -exec sh -c 'echo 0 > {}' ;
Pero usando sh -c
con find -exec
me hace sentir muy inquieto porque sospecho problemas de cotización. Jugué un poco con él y aparentemente mis sospechas estaban justificadas:
-
Mi configuración de prueba:
[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
-
Usando
find -exec
sinsh -c
parece funcionar sin problemas; no es necesario citar aquí:[email protected] ~ % find findtest -type f -exec cat {} ; one two three
-
Pero cuando estoy usando
sh -c
{}
parece requerir algún tipo de cita:[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
-
Las comillas dobles funcionan siempre que ningún nombre de archivo contenga comillas dobles:
[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
-
Las comillas simples funcionan siempre que ningún nombre de archivo contenga comillas simples:
[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
No he encontrado una solución que funcione en todos los casos. ¿Hay algo que estoy pasando por alto o estoy usando sh -c
? en find -exec
intrínsecamente inseguro?
Respuesta aceptada:
Nunca inserte {}
en el código de shell! Eso crea una vulnerabilidad de inyección de comandos. Tenga en cuenta que para cat "{}"
, no se trata solo del "
caracteres, ,
`
, $
también son un problema (considere, por ejemplo, un archivo llamado ./$(reboot)/accept_ra
)¹.
Aquí, le gustaría pasar los nombres de los archivos como argumentos separados a sh
(no en el código argumento), y el sh
secuencia de comandos en línea (el código argumento) para referirse a ellos usando parámetros posicionales:
find . -name accept_ra -exec sh -c 'echo 0 > "$1"' sh {} ;
O, para evitar ejecutar un sh
por archivo:
find . -name accept_ra -exec sh -c 'for file do
echo 0 > "$file"; done' sh {} +
Lo mismo se aplica a xargs -I{}
o zsh
's zargs -I{}
. No escribas:
<list.txt xargs -I{} sh -c 'cmd > {}'
Lo cual sería una vulnerabilidad de inyección de comando de la misma manera que con find
arriba, pero:
<list.txt xargs sh -c 'for file do cmd > "$file"; done' sh
Lo que también tiene la ventaja de evitar ejecutar un sh
por archivo y el error cuando list.txt
no contiene ningún archivo.
Con zsh
los zargs
, probablemente querrá usar una función en lugar de invocar sh -c
:
do-it() cmd > $1
zargs ./*.txt -- do-it
Tenga en cuenta que en todos los ejemplos anteriores, el segundo sh
anterior entra en el $0
del script en línea . Deberías usar algo relevante allí (como sh
o find-sh
), no cosas como _
, -
, --
o la cadena vacía, como el valor en $0
se utiliza para los mensajes de error del shell:
$ find . -name accept_ra -exec sh -c 'echo 0 > "$1"' inline-sh {} ;
inline-sh: ./accept_ra: Permission denied
GNU parallel
funciona de manera diferente. Con él, no quiero usar sh -c
como parallel
ya ejecuta un shell e intenta reemplazar {}
con el argumento citado en la sintaxis correcta para el shell.
<list.txt PARALLEL_SHELL=sh parallel 'cmd > {}'