web-dev-qa-db-ja.com

`sh -c`で実行したシェル式に変数を渡すにはどうすればよいですか?

log_file/2020/04/30のようなフォルダーで実行される次のスクリプトがあります。このフォルダーにはserver.logファイルが含まれています。そして、日付ごとに1つあります。

私のスクリプト

path_date=$(echo "$(pwd)" | grep -oP '\d+/\d+(/\d+)?')
date=${path_date//\//-}
echo date: $date


find ./ -name "server.log*" |  xargs -i sh -c 'filename=$(basename {}) && new_filename=${date}-$filename && echo $(readlink -f {}) ${new_filename}' >> ~/logs/server-logs.list

出力ファイル~/logs/server-logs.listに次のような行が含まれていると思います

log_file/2020/04/30/server.log 2020-04-30-server.log

しかし、代わりにそれは出力しています

log_file/2020/04/30/server.log -server.log

変数$datesh -cのコンテキストに存在しません

現在のシェルからsh -cで実行されるシェル式に変数を渡すにはどうすればよいですか?

1
belun

UnixとLinux SEには この素晴らしい答えStéphaneChazelas があります。
私はそれを複製したくありません、重要な部分だけです:

シェルコードに{}を埋め込まないでください。これにより、コマンドインジェクションの脆弱性が生まれます。

むしろ使用

xargs -I{} sh -c 'echo "$1";' xargs-sh {}

または

find -exec sh -c 'echo "$1";' find-sh {} \;

名前xargs-sh/find-shは単なる名前であり、何でもかまいません(_には多くの名前が表示されます)が、エラーが追跡しやすくなります。エラーメッセージの一部。


ところで:findを使用する場合は、xargsにパイプするのではなく、-execを使用することをお勧めします。それでも何らかの理由でそれを行う場合は、NUL区切りの出力を使用して、ファイル名にあまり一般的ではないが有効な改行が含まれている場合にスクリプトが窒息しないようにします。

find ... -print0 | xargs -0 ...

Sh -cスクリプトに$dateを追加する方法について:

一重引用符で囲まれた変数は展開されません。 これを読む または これ

ただし、この場合は、sh -cスクリプトの引数として日付を追加する方が安全です。

find -exec sh -c 'date="$1"; file="$2"; ...' find-sh "$date" {} \;
3
pLumo