나는 1) 특정 디렉토리($DIR1)에 있는 모든 이미지 파일을 찾아 다른 디렉토리($DIR2)로 이동한 다음 2) 동일한 $DIR1에 있는 모든 비디오 파일을 찾아서 이동하는 bash 스크립트를 작성했습니다. 마지막으로 $DIR1에 남아 있는 모든 파일을 찾아 네 번째 디렉터리($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
이는 스크립트를 개선하려는 시도입니다. 오류 논리를 더 쉽게 추가할 수 있도록 대형 파이프가 제거되었습니다. 또한 계산 논리를 더 쉽게 추가할 수 있습니다. 또한 디렉터리를 세 번 읽지 않고 한 번 읽으므로 속도가 약간 향상될 수 있습니다. 또한 쉘 변수 하위 문자열 제거 및 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