Bashの呼び出しと配列

Bashの呼び出しと配列

私は初めて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)

おすすめ記事