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
変数$date
はsh -c
のコンテキストに存在しません
現在のシェルからsh -c
で実行されるシェル式に変数を渡すにはどうすればよいですか?
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" {} \;