我编写了一个bash脚本,1)查找某个目录($DIR1)中的所有图像文件并将它们移动到另一个目录($DIR2)然后2)查找同一$DIR1中的所有视频文件并将它们移动到第三个目录($DIR3),最后找到 $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
这是改进脚本的尝试。大型管道被删除,以便更轻松地添加任何错误逻辑。它还可以更轻松地添加计数逻辑。此外,由于我们读取目录一次而不是三次,因此速度可能会略有提高。此外,通过使用 shell 变量子字符串删除和 case 语句(以及不同的参数)来剪切(以及 grep 和 sed)file
。
至于错误检查,外部 DIR1/2/3/4 变量周围有引号,并测试它们是开头的目录。我使用 Bash FAQ 中的空终止文件名技术(此处: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