使用 "find" 和 "avconv" 转换多个递归视频文件
Convert multiple recursive video files using "find" and "avconv"
为了将目录中的 MOV 文件转换为 mp4,我使用了(我使用更多命令与 avconv,但我缩短了 syntetize):
for f in *.MOV; do echo "Converting $f"; avconv -i "$f" "${f:0: -4}.mp4"; done
并且有效。它转换每个文件。
但是现在,我想转换目录和所有子目录中的所有文件(递归)。我试过了:
for f in "$(find ./ -name '*.MOV')"; do echo "Converting $f"; avconv -i "$f" "${f:0: -4}.mp4"; done
但它不起作用,因为它输出:
mario@circo3d:~/Imágenes$ for f in "$(find ./ -name '*.MOV')"; do echo "Converting $f"; avconv -i "$f" "${f:0: -4}.mp4"; done
Converting ./2015-05-23 Tutorial Masa de colores/MVI_9219.MOV
./2015-05-23 Tutorial Masa de colores/MVI_9196.MOV
./2015-05-23 Tutorial Masa de colores/MVI_9199.MOV
./2015-05-23 Tutorial Masa de colores/MVI_9200.MOV
avconv version 9.18-6:9.18-0ubuntu0.14.04.1, Copyright (c) 2000-2014 the Libav developers built on Mar 16 2015 13:19:10 with gcc 4.8 (Ubuntu 4.8.2-19ubuntu1)
./2015-05-23 Tutorial Masa de colores/MVI_9219.MOV
./2015-05-23 Tutorial Masa de colores/MVI_9196.MOV
./2015-05-23 Tutorial Masa de colores/MVI_9199.MOV
mario@circo3d:~/Imágenes$
(最后一个文件列表显示为红色)
似乎 find 有效,它进入每个目录并且 echo "Converting $f" 也...但是 avconv 收到所有文件名都是带有换行符的列表,而不是 "for" 循环中的每个元素。
为什么 echo 有效而 avconv 无效?
或者...
为什么 for f in *.MOV' 使用 avconv 而 for f in "$(find ./ -name '*.MOV') 不是吗?
这是因为您将它们放在引号中。在 POSIX 中,换行符可以很好地出现在文件名中。
最简单的解决方案是使用 find 的 -exec
属性重写:
find . -name "*.MTS" -exec echo {} \; -exec avconv -i {} {}.mp4 \;
或者更好的是,您可以在 avconv
行中使用 -execdir
,它将从找到文件的目录中执行命令。
从您的评论中,我发现您很难看出换行符的来源。所以
来自 find 的手册页:
If no expression is given, the expression -print is used
和
-print True; print the full file name on the standard output, followed
by a newline.
所以 find 实际上会为您打印所有换行符。您通过 $(find ...)
调用它,然后将其放在引号中,这意味着所有换行符都保留为常规字符。
这就是为什么您的 for 循环只执行一次的原因。
如果你绝对必须使用循环,而不是使用 find
自己的执行,你可能想要使用 while 循环:
find . -name "*.MTS" | while read f; do echo "Converting $f"; avconv -i "$f" "${f:0: -4}.mp4"; done
我使用 sox 将 mp3 转换为 alaw 文件。非常相似的情况。使用简单的 bash 脚本。
#!/bin/bash
for file in $(find . -name '*.mp3')
do
echo $file
sox $file -t al -c 1 -r 8000 $(echo "$file" | sed -r 's|.mp3|.alaw|g')
done
为了将目录中的 MOV 文件转换为 mp4,我使用了(我使用更多命令与 avconv,但我缩短了 syntetize):
for f in *.MOV; do echo "Converting $f"; avconv -i "$f" "${f:0: -4}.mp4"; done
并且有效。它转换每个文件。
但是现在,我想转换目录和所有子目录中的所有文件(递归)。我试过了:
for f in "$(find ./ -name '*.MOV')"; do echo "Converting $f"; avconv -i "$f" "${f:0: -4}.mp4"; done
但它不起作用,因为它输出:
mario@circo3d:~/Imágenes$ for f in "$(find ./ -name '*.MOV')"; do echo "Converting $f"; avconv -i "$f" "${f:0: -4}.mp4"; done
Converting ./2015-05-23 Tutorial Masa de colores/MVI_9219.MOV
./2015-05-23 Tutorial Masa de colores/MVI_9196.MOV
./2015-05-23 Tutorial Masa de colores/MVI_9199.MOV
./2015-05-23 Tutorial Masa de colores/MVI_9200.MOV
avconv version 9.18-6:9.18-0ubuntu0.14.04.1, Copyright (c) 2000-2014 the Libav developers built on Mar 16 2015 13:19:10 with gcc 4.8 (Ubuntu 4.8.2-19ubuntu1)
./2015-05-23 Tutorial Masa de colores/MVI_9219.MOV
./2015-05-23 Tutorial Masa de colores/MVI_9196.MOV
./2015-05-23 Tutorial Masa de colores/MVI_9199.MOV
mario@circo3d:~/Imágenes$
(最后一个文件列表显示为红色)
似乎 find 有效,它进入每个目录并且 echo "Converting $f" 也...但是 avconv 收到所有文件名都是带有换行符的列表,而不是 "for" 循环中的每个元素。
为什么 echo 有效而 avconv 无效?
或者...
为什么 for f in *.MOV' 使用 avconv 而 for f in "$(find ./ -name '*.MOV') 不是吗?
这是因为您将它们放在引号中。在 POSIX 中,换行符可以很好地出现在文件名中。
最简单的解决方案是使用 find 的 -exec
属性重写:
find . -name "*.MTS" -exec echo {} \; -exec avconv -i {} {}.mp4 \;
或者更好的是,您可以在 avconv
行中使用 -execdir
,它将从找到文件的目录中执行命令。
从您的评论中,我发现您很难看出换行符的来源。所以
来自 find 的手册页:
If no expression is given, the expression -print is used
和
-print True; print the full file name on the standard output, followed
by a newline.
所以 find 实际上会为您打印所有换行符。您通过 $(find ...)
调用它,然后将其放在引号中,这意味着所有换行符都保留为常规字符。
这就是为什么您的 for 循环只执行一次的原因。
如果你绝对必须使用循环,而不是使用 find
自己的执行,你可能想要使用 while 循环:
find . -name "*.MTS" | while read f; do echo "Converting $f"; avconv -i "$f" "${f:0: -4}.mp4"; done
我使用 sox 将 mp3 转换为 alaw 文件。非常相似的情况。使用简单的 bash 脚本。
#!/bin/bash
for file in $(find . -name '*.mp3')
do
echo $file
sox $file -t al -c 1 -r 8000 $(echo "$file" | sed -r 's|.mp3|.alaw|g')
done