내가 사용하려고 해요 find
로 echo 0
일부 파일에,하지만 분명히 이것은 단지와 함께 작동합니다 sh -c
:
find /proc/sys/net/ipv6 -name accept_ra -exec sh -c 'echo 0 > {}' \;
그러나 sh -c
with find -exec
을 사용 하면 인용 문제가 의심되므로 매우 불편합니다. 나는 그것으로 조금 바이올린을 썼고 분명히 내 의심은 정당화되었다.
-
내 테스트 설정 :
martin@dogmeat ~ % cd findtest martin@dogmeat ~/findtest % echo one > file\ with\ spaces martin@dogmeat ~/findtest % echo two > file\ with\ \'single\ quotes\' martin@dogmeat ~/findtest % echo three > file\ with\ \"double\ quotes\" martin@dogmeat ~/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
-
find -exec
없이 사용하면sh -c
문제없이 작동하는 것 같습니다.martin@dogmeat ~ % find findtest -type f -exec cat {} \; one two three
-
그러나 내가 사용할 때
sh -c
{}
어떤 종류의 인용이 필요한 것 같습니다.martin@dogmeat ~ % 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
-
큰 따옴표는 파일 이름에 큰 따옴표가없는 한 작동합니다.
martin@dogmeat ~ % 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
-
작은 따옴표는 파일 이름에 작은 따옴표가 포함되지 않는 한 작동합니다.
martin@dogmeat ~ % 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
모든 경우에 작동하는 솔루션을 찾지 못했습니다. 내가 간과하거나 본질적으로 안전하지 않은 것을 사용 sh -c
하고 find -exec
있습니까?
답변
{}
쉘 코드에 포함시키지 마십시오 ! 명령 주입 취약점이 발생합니다. 주를 위해 것을 cat "{}"
그것의의에 대해서뿐만 아니라 "
문자, \
, `
, $
또한 문제가 있습니다 (예를 들어라는 파일을 고려 ./$(reboot)/accept_ra
).
(그런데, 일부 find
구현에서는 그렇게 할 수 없으며 POSIX{}
는에 대한 인수에서 자체가 아닌 경우 동작을 지정 하지 않은 채로 둡니다find
)
여기에서 파일 이름을 별도의 인수로 sh
( 코드 인수가 아닌 ) 및 sh
인라인 스크립트 ( 코드 인수)로 전달하여 위치 매개 변수를 사용하여 파일 이름 을 참조하려고합니다.
find . -name accept_ra -exec sh -c 'echo 0 > "$1"' sh {} \;
또는 sh
파일 당 하나를 실행하지 않으려면 다음을 수행 하십시오.
find . -name accept_ra -exec sh -c 'for file do
echo 0 > "$file"; done' sh {} +
동일 적용 xargs -I{}
또는 zsh
의 zargs -I{}
. 쓰지 마십시오 :
<list.txt xargs -I {} sh -c 'cmd> {}'
find
위와 같은 방법으로 명령 주입 취약점이 될 수 있지만,
<list.txt xargs sh -c 'for file do cmd > "$file"; done' sh
또한 sh
파일 당 하나를 실행 list.txt
하지 않고 파일이 포함되지 않은 경우 오류 를 피할 수 있다는 이점이 있습니다.
함께 zsh
S ‘ zargs
, 당신은 아마 호출보다는 기능을 사용하고자하는 것입니다 sh -c
:
do-it() cmd > $1
zargs ./*.txt -- do-it
위의 모든 예제에서 위의 두 번째 예제 sh
는 인라인 스크립트로 이동합니다 $0
. 당신이 관련 일을 (같이 사용해야 sh
또는 find-sh
)가 아닌 상황이 좋아 _
, -
, --
, 또는 빈 문자열 값으로 $0
쉘의 오류 메시지에 사용됩니다 :
$ find . -name accept_ra -exec sh -c 'echo 0 > "$1"' inline-sh {} \;
inline-sh: ./accept_ra: Permission denied
GNU parallel
는 다르게 작동합니다. 그것으로, 당신은 이미 쉘을 실행하는 것처럼 사용하고 싶지 않으며 쉘 에 대한 올바른 구문에서 인용 된 인수 로 대체하려고합니다 .sh -c
parallel
{}
<list.txt PARALLEL_SHELL=sh parallel 'cmd > {}'