特定のファイル形式を見つけて移動できるようにbashスクリプトを改善するのに役立ちます。

特定のファイル形式を見つけて移動できるようにbashスクリプトを改善するのに役立ちます。

私は1)特定のディレクトリ($ DIR1)にあるすべての画像ファイルを見つけて別のディレクトリ($ DIR2)に移動し、2)同じ$ DIR1にあるすべてのビデオファイルを見つけて移動するbashスクリプトを作成しました。最後に、$ DIR1に残っているすべてのファイルを見つけて、4番目のディレクトリ($ DIR4)に移動します。最終結果は、スクリプトの最後に$ DIR1が空であることです。

#!/bin/bash 

if [ "$(ls -A $DIR1)" ]; then
        echo "moving all photo files to processing directory"
        find $DIR1 -name '*' -exec file {} \; | grep -o -P '^.+: \w+ image' | cut -d':' -f1 | xargs -I{} mv --backup=numbered {} $DIR2;
    else
        echo "directory is empty, skipping"
    fi

if [ "$(ls -A $DIR1)" ]; then
    echo "moving all video files to processing directory"
    find $DIR1 -type f -exec file -N -i -- {} + | sed -n 's!: video/[^:]*$!!p' | cut -d':' -f1 | xargs -I{} mv --backup=numbered {} $DIR3;
else
    echo "directory is empty, skipping"
fi

if [ "$(ls -A $DIR1)" ]; then
    echo "moving all remaining files to manual-review directory"
find $DIR1 -type f -print0 | xargs -0 mv --backup=numbered -t $DIR4;
else
    echo "no remaining files to move, skipping"
fi

スクリプトが期待どおりに動作するようです。数ヶ月間定期的に実行してみましたが、結果は予想通りです。しかし、これをより良くする方法、特に1)毎回移動されたファイルの数を計算してSTDOUTに印刷する方法、2)スクリプトが正しく機能することを確認するためにいくつかの基本的なエラーチェックを追加する方法を見つけるのに役立ちます必要です。期待どおりに動作しますか?

ベストアンサー1

これはスクリプトを改善する試みです。エラーロジックを簡単に追加できるように、大きなパイプが削除されました。また、計算ロジックを簡単に追加できます。また、ディレクトリを3回読み取らずに1回読み取るので、速度が若干向上する可能性があります。また、シェル変数の部分文字列を削除し、Caseステートメント(および他のパラメータ)を使用して切り取り(およびgrepとsed)file

エラーチェックの場合は、外部 DIR1/2/3/4 変数を引用符で囲み、これがディレクトリの開始かどうかをテストします。私はBash FAQのnull終了ファイル名技術を使用しています(ここでは:http://mywiki.wooledge.org/BashFAQ/020)。これが発生すると、ファイル名にスペースを入れることができます。もちろん、mv失敗したりクラッシュしたりした場合など、file追加できる特別なケースがいくつかあります。

#!/bin/bash 

if [[ ! -d "$DIR1" || ! -d "$DIR2" || ! -d "$DIR3" || ! -d "$DIR3" ]]; then
    echo "missing environment variables or variables aren't directories" >&2
    exit 1
fi

num_images=0
num_videos=0
num_misc=0

echo STARTING
while IFS= read -r -d $'\0' file; do
   mime=$( file -b --mime-type "$file" )
   case "${mime%%/*}" in
      image)
         output="$DIR2"
         ((num_images++))
        ;;
      video)
         output="$DIR3"
         ((num_videos++))
        ;;
      *)
         output="$DIR4"
         ((num_misc++))
        ;;
    esac
    mv "$file" "$output"
done < <( find "$DIR1" -type f -print0 )

echo FINISHED: moved $num_images images, $num_videos videos, $num_misc other files

おすすめ記事