我尽最大努力完成这项工作,但对脚本编写知之甚少。该脚本应该扫描我指定的目录和所有子目录,扫描视频资源,将任何损坏/错误的文件移动到已创建的 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
或类似的操作。echo1
echo
$?
修复上述拼写错误将导致 shell
$?
用 的退出状态覆盖echo
,因此$RC
稍后不会反映 的退出状态ffmpeg
,而是反映 的退出状态echo
。无需将命令的退出状态保存在单独的变量中,然后针对零进行测试,而是直接在语句中使用该命令
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