BASH スクリプトを使用してサブフォルダー ${ROOTPATH}/${subdir} をスキャン

BASH スクリプトを使用してサブフォルダー ${ROOTPATH}/${subdir} をスキャン

私は最善を尽くしましたが、スクリプトについて知っていることはほとんどありません。スクリプトは、私が指定したディレクトリとすべてのサブディレクトリを検索し、ビデオリソースを検索し、破損または誤ったファイルを生成した00errorsフォルダに移動する必要があります。

スキャンするすべてのサブディレクトリを許可して、すべてがうまく機能するようにします。どんな助けでも大変感謝します。

#!/bin/bash

ROOTPATH="/Volumes/ARC-RAID/STORAGE/ASSET-Processing/Movies/LANDSCAPE/BRAND-RECOVERED/BRAND-RECOVERED-LANDSCAPE "
for subdir in *; do
  cd ${ROOTPATH}/${subdir}
  mkdir 00errors
  
  for path in *.{MOV,mov,MP4,mp4}; do

    ffmpeg -i "${path}" -f null -; echo$?
    RC=$?

    if [ "${RC}" -ne "0" ]; then
        # Do something to handle the error.
        mv ${path} ./00errors
    fi

  done
  cd ../
done

ベストアンサー1

コードを詳しく見ていませんが、次のことをお勧めしますfind

#!/bin/sh

topdir=/Volumes/ARC-RAID/STORAGE/ASSET-Processing/Movies/LANDSCAPE/BRAND-RECOVERED/BRAND-RECOVERED-LANDSCAPE

find "$topdir" -name 00error -prune -o \
    -type f \( -iname '*.mp4' -o -iname '*.mov' \) \
    ! -exec ffmpeg -i {} -f null /dev/null \; \
    -execdir mkdir -p 00error \; \
    -execdir mv -- {} 00error \;

または、次から短いインラインshスクリプトを呼び出しますfind

#!/bin/sh

topdir=/Volumes/ARC-RAID/STORAGE/ASSET-Processing/Movies/LANDSCAPE/BRAND-RECOVERED/BRAND-RECOVERED-LANDSCAPE

find "$topdir" -name 00error -prune -o \
    -type f \( -iname '*.mp4' -o -iname '*.mov' \) -exec sh -c '
    for pathname do
        if ! ffmpeg -i "$pathname" -f null /dev/null; then
            dirpath=${pathname%/*}
            mkdir -p "$dirpath"/00error
            mv "$pathname" "$dirpath"/00error
        fi
    done' sh {} +

どちらのバリエーションも、ファイル名の大文字と小文字を区別しない一致をfind理解するパターンがあり、見つかったファイルのディレクトリでユーティリティを実行することを理解しているとします。どちらも非標準です。-iname-execdir-iname-execdir

これは最上位ディレクトリの下のすべてのムービーファイルを選択するので、スクリプトほどディレクトリ構造は厳密ではありません。


あなたのコードに関して:

  • 私が見つけた値はROOTPATH最後にスペースがあります。これは偶然かもしれません。

  • echo$?echo0との間に欠けているスペースがあるため、類似または類似の操作が試みられます。echo1echo$?

  • $?上記のタイプミスを修正すると、シャットダウンが終了状態で上書きされるため、後で終了状態が反映されるのではなく終了状態が反映されechoます。$RCffmpegecho

  • コマンドの終了ステータスを別の変数に保存してから0をテストするのではなく、ステートメントで直接コマンドを使用してくださいif。上記のコマンドの2番目のバリエーションでこれを行いましたfind

  • *ディレクトリ名とディレクトリ以外の名前を一致させることができます。そのため、使用がcd ${ROOTPATH}/${subdir}失敗する可能性があります(ディレクトリの末尾のスペースなど、ディレクトリ名にスペースが含まれているか、ディレクトリが空であるROOTPATHため失敗する可能性があります)。失敗すると、cd内部ループが誤ったファイルを処理している可能性があり、さらに下に下がるとcd ..レベルが高すぎます。

以下は修正されたコードバリアントです。

#!/bin/bash

topdir=/Volumes/ARC-RAID/STORAGE/ASSET-Processing/Movies/LANDSCAPE/BRAND-RECOVERED/BRAND-RECOVERED-LANDSCAPE

# Make globbing case-insensitive (nocaseglob), and
# make patterns disappear if not matched (nullglob)
shopt -s nullglob nocaseglob

for subdir in "$topdir"/*/; do
    for mov in "$subdir"/*.{mov,mp4}; do
        if [ -f "$mov" ] && ! ffmpeg -i "$mov" -f null /dev/null; then
            mkdir -p "$subdir"/00error &&
            mv "$mov" "$subdir"/00error
        fi
    done
done

ご覧のとおり、cd必要ありません。

内部ループがない場合:

#!/bin/bash

topdir=/Volumes/ARC-RAID/STORAGE/ASSET-Processing/Movies/LANDSCAPE/BRAND-RECOVERED/BRAND-RECOVERED-LANDSCAPE

shopt -s nocaseglob nullglob

for mov in "$topdir"/*/*.{mov,mp4}; do
    if [ -f "$mov" ] && ! ffmpeg -i "$mov" -f null /dev/null; then
        mkdir -p "${mov%/*}"/00error &&
        mv "$mov" "${mov%/*}"/00error
    fi
done

おすすめ記事