我正在编写一个shell脚本,通过Handbrake从我的相机批处理.mov文件以节省高清空间。该脚本使用“find”搜索目录,然后在找到的每个.mov文件上运行Handbrake,将生成的文件的创建日期与源文件的日期匹配为“touch”。
我最初使用 for 循环执行此操作:
for i in $(find "$*" -iname '*.mov') ; do
~/Unix/HandbrakeCLI --input "$i" --output "$i".mp4 --preset="Normal"
touch -r "$i" "$i".mp4
done
这很有效,但如果输入文件的文件名中有空格,则会失败。所以我尝试了一个而循环:
find "$*" -iname '*.mov' | while read i ; do
~/Unix/HandbrakeCLI --input "$i" --output "$i".mp4 --preset="Normal"
touch -r "$i" "$i".mp4
done
此循环的问题在于它适用于目录中的第一个文件,然后退出循环。请注意,如果我在while循环体中替换“echo $ i”,它会打印目录中的所有.mov文件,因此循环结构正确。
我相信我对this stackoverflow thread的问题有部分答案。但该解决方案特定于ssh,并不能解决一般问题。似乎与子进程使用的stdin有关,但我不完全理解它是如何工作的。
有什么建议吗?
我在OSX 10.6上
答案 0 :(得分:2)
一种可能性是使用safe find:
while IFS= read -r -d '' -u 9
do
~/Unix/HandbrakeCLI --input "$REPLY" --output "$REPLY".mp4 --preset="Normal"
touch -r "$REPLY" "$REPLY".mp4
done 9< <( find "$@" -type f -print0 )
这应该与POSIX兼容,但只有HandbrakeCLI
和touch
从标准输入和读取的文件名都不包含换行符时才有效:
find "$@" -type f -print0 | while IFS= read -r
do
~/Unix/HandbrakeCLI --input "$REPLY" --output "$REPLY".mp4 --preset="Normal"
touch -r "$REPLY" "$REPLY".mp4
done
答案 1 :(得分:2)
取自this answer:我现在没有回应HandbrakeCLI,以确保它不使用与我的脚本相同的标准输出:
find . -name "*.mkv" | while read FILE
do
echo "" | handbrake-touch "$FILE"
if [ $? != 0 ]
then
echo "$FILE had problems" >> errors.log
fi
done
......它按预期/预期工作。
答案 2 :(得分:1)
您可能正在运行shellopt'-e'(退出错误)
尝试
set +e
答案 3 :(得分:0)
此链接在Ubuntu Linux 11.04上修复了我的问题。
Preventing a child process (HandbrakeCLI) from causing the parent script to exit
以下是适用于我的代码:
ls -t *.mpeg | tail -n +2 | while read name
do echo "$name" ; in="$name" ; out=coded/"`echo $name | sed 's/.mpeg$/.mkv/'`"
echo "" | HandBrakeCLI -i "$in" -o "$out" -a '1,2' ; mv -v "$name" trash/"$name"
done
答案 4 :(得分:0)
我遇到了同样的问题。我认为HandbrakeCLI正在消耗stdin。我这里没有我的实际系统,但我的测试显示可能发生的事情。
“output”是一个数字为1-10的文件,每个文件都在各自的行上。
while read line ; do echo "MAIN: $line"; ./consumer.sh; done < output
consumer.sh:
#!/bin/sh
while read line ; do
echo "CONSUMER: $line"
done
结果:
MAIN: 1
CONSUMER: 2
CONSUMER: 3
CONSUMER: 4
CONSUMER: 5
CONSUMER: 6
CONSUMER: 7
CONSUMER: 8
CONSUMER: 9
CONSUMER: 10
更改外部while循环将解决问题:
while read line ; do echo "MAIN: $line"; ./consumer.sh < /dev/null; done < output
结果:
MAIN: 1
MAIN: 2
MAIN: 3
MAIN: 4
MAIN: 5
MAIN: 6
MAIN: 7
MAIN: 8
MAIN: 9
MAIN: 10
答案 5 :(得分:0)
考虑使用find
来调用shell,而不是将find
包裹在while
循环中。
find "$@" -iname '*.mov' -exec sh -c '
~/Unix/HandbrakeCLI --input "$1" --output "$1".mp4 --preset="Normal"
touch -r "$1" "$1".mp4
' _ {} ';'