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. 위 명령의 두 번째 변형에서 이 작업을 수행했습니다 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

관련 정보