find
を使用しようとしています echo 0
へ 一部のファイルに追加されますが、これは sh -c
でのみ機能するようです。 :
find /proc/sys/net/ipv6 -name accept_ra -exec sh -c 'echo 0 > {}' ;
ただし、 sh -c
を使用する find -exec
を使用 引用の問題が疑われるので、とても不安になります。私はそれを少しいじりました、そして明らかに私の疑いは正当化されました:
-
私のテスト設定:
[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
-
find -exec
を使用するsh -c
なし 問題なく動作しているようです–ここで引用する必要はありません:[email protected] ~ % find findtest -type f -exec cat {} ; one two three
-
しかし、
sh -c
を使用している場合{}
ある種の引用が必要なようです:[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
-
二重引用符は、ファイル名に二重引用符が含まれていない限り機能します:
[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
-
一重引用符は、ファイル名に一重引用符が含まれていない限り機能します:
[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
すべての場合に機能する解決策は見つかりませんでした。私が見落としているもの、または sh -c
を使用しているものはありますか find -exec
で 本質的に安全ではありませんか?
承認された回答:
{}
を埋め込まないでください シェルコードで!これにより、コマンドインジェクションの脆弱性が発生します。 cat "{}"
の場合は注意してください 、それは"
だけではありません 文字、
、 `
、 $
これも問題です(たとえば、 ./ $(reboot)/ accept_ra
というファイルを考えてみてください。 )¹。
ここでは、ファイル名を個別の引数として sh
に渡します。 (コードにはありません 引数)、および sh
インラインスクリプト(コード 引数)位置パラメータを使用してそれらを参照するには:
find . -name accept_ra -exec sh -c 'echo 0 > "$1"' sh {} ;
または、1つの 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
これには、1つの sh
の実行を回避できるという利点もあります。 ファイルごと、および list.txt
の場合のエラー ファイルが含まれていません。
zsh
を使用 のzargs
、 sh -c
を呼び出すのではなく、関数を使用することをお勧めします。 :
do-it() cmd > $1
zargs ./*.txt -- do-it
上記のすべての例で、2番目の 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パラレルコード> 動作が異なります。それを使用すると、しない
sh -c
を使用したい parallel
として すでにシェルを実行していて、 {}
を置き換えようとします シェルの正しい構文で引用された引数を使用します。
<list.txt PARALLEL_SHELL=sh parallel 'cmd > {}'