私は初めてbashスクリプトに触れ、まだドラフトですが、このスクリプトは期待どおりに機能しました。
#!/bin/bash
find /var/www/site.com/ -type f -name "*.log" | xargs bash -c '
for name; do
parent=${name%/*}
parent=${parent##*/}
destdir=$(dirname $name)
current_year=$(date +"%Y")
if [[ "$name" =~ _([0-9]{4})- ]] &&
[[ "$name" != *"$current_year"* ]]; then
year="${BASH_REMATCH[1]}"
else continue
fi
if [ ! -d "$destdir/$year/$parent" ]; then
mkdir -p "$destdir/$year/"
fi
mv "$name" "$destdir/$year"
done '
find /var/www/site.com/ -type d -name "20*" | xargs bash -c '
for dir; do
tar_name=$(echo $dir | grep -Eo '[0-9]{4}')
tar cvfj '$tar_name'.tbz $dir
done '
exit
ご覧のとおり、bashスクリプトでbashを2回呼び出しました。これは悪い習慣ですか?話すことはできませんか?それとも、findコマンドの出力を使用して配列を作成して繰り返す方が良いですか?どんなアドバイスも本当にありがとうございます。よろしくお願いします。 PSインデントが足りないので申し訳ありません
答え1
内部シェルスクリプトを見なくてもいくつかの注意事項があります。
ファイル名にスペース、引用符、またはバックスラッシュ文字が含まれていると、通常のxargs
操作は失敗します。これには、他のほとんどの引用規則と互換性のない自己引用規則のセットがあります。 (今は参考質問が見つかりません。)
インラインシェルスクリプトに「0番目」引数がないため、最初のファイル名をスキップします。
また、構文の強調表示は、2番目のコマンドが壊れていることを示しています。grep -Eo '[0-9]{4}'
スクリプト全体の周りに一重引用符を閉じて再度開く引用符があります。
この問題はxargs
簡単に解決され、find ... -print0 | xargs -0 command...
多くの実装(GNU、FreeBSD、Busybox)がこれをサポートしています。
0番目のパラメータの問題を解決するには、ダミーパラメータ(で終わる$0
)を追加する必要があります。
... | xargs -0 bash -c '...' sh
またはfind ... -exec bash -c '...' sh {} +
。
しかし、他のシェルを起動しないことをお勧めします。 Bashでは、次のことができます。
find ... -print0 | while IFS= read -r -d '' file; do
something with "$file"
done
または、
while IFS= read -r -d '' file; do
something with "$file"
done < <(find ... -print0)
後者は、ループ内で変数を設定し、ループ外で変数を使用できると予想される場合にも機能します。
関連セクションを見る検索結果を繰り返すのはなぜ悪い習慣ですか?(コマンド置換を使用しないため、すべてが関連しているわけではありません。)
出力をfind
配列に入れるには、次のようにします。
mapfile -t -d '' array < <(find ... -print0)
答え2
bashが≥4.3であると仮定すると、呼び出しの代わりに再帰ワイルドカードを使用できますfind
。find
呼び出しには問題はありませんが(正しく実行した場合:以下を参照)、再帰ワイルドカードが機能するときはあまり便利ではありません。電話する必要がありますshopt -s globstar
再帰的なワイルドカードを有効にします。
shopt -s globstar
for name in /var/www/site.com/**/*.log; do
…
done
for dir in /var/www/site.com/**/20*/; do
…
done
1つを使用している場合は、パイプでfind
接続しないでください。ファイル名を区別するために別の構文を使用するため、名前にスペースが含まれている場合はシェル呼び出しを使用するか、 。find
xargs
\'"
-exec
find … -print0 | xargs -0
スペースやその他の特殊文字が原因でシェルスクリプトが停止するのはなぜですか?より多くの情報を知りたいです。