私はいくつかのファイルでfind
toを使用しようとしましたが、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
安全でないものを使用しているものはありますか?
ベストアンサー1
{}
シェルコードを挿入しないでください。これによりコマンドインジェクションの脆弱性が発生します。の場合、文字に関するものだけでなく問題もcat "{}"
あります(例えばというファイルを考慮)。"
\
`
$
./$(reboot)/accept_ra
(ちなみに、いくつかのfind
実装あなたはこのようなことをするようにしません。POSIX脱退アクション指定されていないの引数に{}
単独で存在しない場合)find -exec
sh
ここでは、ファイル名を別の引数として(代わりに)渡そうとします。パスワードパラメータ)とsh
インラインスクリプト(パスワード引数)位置引数を使用して参照してください。
find . -name accept_ra -exec sh -c 'echo 0 > "$1"' sh {} \;
またはsh
ファイルごとに1つずつ実行したくない場合は、次のようにします。
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
s の場合、zargs
次を呼び出す代わりに関数を使用できますsh -c
。
do-it() cmd > $1
zargs -l1 ./*.txt -- do-it
zshでループを使用することもできますが、for
非常に短いことがあります。
for f (*.txt) cmd > $f
(ただし、最後の失敗以外の失敗は全終了cmd
状態には報告されません。)
上記のすべての例では、sh
上記の2番目の項目はインラインスクリプトに入ります。などの項目や空の文字列ではなく、関連項目(orなど)を$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 > {}'
実装に応じて、sh
他の文字のエンコーディングにはこれらの文字のエンコーディングが含まれます(実際のおよび実際の文字エンコーディングでは、バイト0x5cおよび0x60に制限されます)