如何与xargs一起使用两个参数?


18

我需要转换视频,但是我不知道它们在哪里,所以我需要find它们。我怎么能放弃的结果和输出文件名的FFmpegxargs

我已经发现可以使用此命令构造两个参数:

find . -iname "*.mov" -printf "%p %f\n"

我在xargs手册中找不到任何相关内容。我想要这样的东西:

find . -iname "*.mov" -printf "%p %f\n" | xargs ffmpeg -i {param1} -f flv {param2}

我怎样才能做到这一点?


那些在此问题上绊脚石的人,因为您xargs 通常在寻找有关多个参数的答案,所以可能想查看stackoverflow.com/questions/3770432/…
克里斯·奥尔德伍德

Answers:


4

诸如此类的事情将可以解决问题,并保留完整路径,处理空间,重命名folder/movie.movfolder/movie.flv,等等。

find . -name "*.mov" | while read movie;do
  ffmpeg -i "$movie" -f flv "${movie%.mov}.flv"
done

如果我误解了您,并且您希望当前目录中的所有.flv电影都可以使用,请改用以下目录:

find . -name "*.mov" | while read movie;do
  ffmpeg -i "$movie" -f flv "$(basename "${movie%.mov}.flv")"
done

3
如果您希望将它作为单线,只需将所有内容放在一行上即可。;)
Mattias Ahnberg 2012年

9

人们xargs与find结合使用的原因是,无论xargs启动什么程序,多个文件名都将传递给同一程序调用。例如,如果find返回文件foobarbaz,则以下内容将mv仅运行一次:

find sourceDir [...] -print0 | xargs -0 mv -t destDir

实际上,它的调用mv类似于以下内容:

mv -t destDir foo bar baz

如果你不需要或不想要这种行为(我认为是这里的情况),你可以简单地使用find-exec


在这种情况下,一个简单的解决方案是编写一个简短的shell脚本,如下所示:

#!/usr/bin/env bash
[[ -f "$1" ]] || { echo "$1 not found" ; exit 1 ; }
P="$1"
F="$( basename $P )"
ffmpeg -i "$P" -f flv "$F"

另存为myffmpeg.sh并运行chmod +x myffmpeg.sh。然后,运行以下命令:

find . -iname "*.mov" -exec /path/to/myffmpeg.sh {} \;

这将为找到的每个文件调用一次shell脚本。Shell脚本反过来从完整路径中提取文件名,并ffmpeg使用适当的参数进行调用。


4

我没有得到我期望的解决方案,所以我找到了自己的解决方案。@Daniel的回答很好,但是需要一个shell脚本。一个衬板更快,我更喜欢它:)比编写脚本还简单的解决方案。

我可以使用一个参数,basename并使用和处理它sh -c

find . -iname "*.mov" -print0 | xargs -0 -i sh -c 'ffmpeg -i {} -f flv `basename {}`'

-i告诉xargs {}用当前参数替换。
``内的命令输出打印为标准输出(bash功能),因此basename {}将被评估为裸文件名并打印出来。
-0用于正确处理特殊文件名,但是您需要使用带有-print0选项的参数和find一起传递


3

您必须像上面的所有答案一样来做,但是xargs的精确使用将是这样的:

echo argument1 argument2 argument3 | xargs -l bash -c 'echo this is first:$0 second:$1 third:$2' | xargs

因此,在您的情况下,它将是:

find . -iname "*.mov" -printf "%p %f\n" | xargs -l bash -c 'echo ffmpeg -i $0 -f flv $1' | xargs

PS:这为正在xargs一个xargs命令中为多个参数精确寻找答案的人回答了有关xargs的问题。


1

为什么不简单地移动ffmpeg的选项以适合find命令的结果格式呢?

find . -iname "*.mov" -printf "%p %f\n" | xargs -r -n2 ffmpeg -f flv -i

请注意,在xargs中添加了-r选项,以防止在未找到.mov文件的情况下运行ffmpeg

我在xargs中添加了-n2选项,以将xargs进程的项数一次限制为两个。在这种情况下,项目是文件路径和文件名。如果未设置-n选项,则xargs将在一次执行中处理尽可能多的输入项。


一旦找到AFAICT多个文件,此功能将不起作用。
丹尼尔·贝克

这对我也只起作用一次,但是我不明白为什么它在第一次之后就停止了。任何想法 ?
kissgyorgy 2012年

实际上它不起作用
kissgyorgy 2012年

Daniel-Beck和@Walkman对于单次执行是正确的。为了解决该问题,我编辑了此答案,以通过-n2选项限制一次xargs进程的项数。如果没有-n2,则xargs如果可以处理通过管道接收到的输入项的数量,则仅执行一次。还应该指出的是,该解决方案仅在文件名和文件路径不包含空格的情况下才有效。
ZaSter 2012年

1

我不确定是否可以使用xargs或如何使用xargs。

但是这样的事情应该对您有用:

find . -iname "*.mov" -printf "%p %f\n" | while read -a HR ; do echo ffmpeg -i ${HR[0]} -f flv ${HR[1]} ;done

1
这不能正确处理文件名/路径中的空格,对吗?
丹尼尔·贝克

1

Zoredache的答案的另一种选择是使用名称绑定(并使用不同的分隔符以避免文件名中出现空格):

IFS="\t" find -iname "*.mov" -printf "%p\t%f\n" | while read path file; do
    ffmpeg -i $path -f flv $file
done

当然,您也可以将分隔符与find -a array其他答案使用的参数一起使用,但是有时命名的参数更容易理解。


0

您可以像这样直接从find命令运行ffmpeg:

find . -iname "*.mov" -exec ffmpeg -i "%p" -f flv "%f" \;

请注意ffmpeg的参数周围的引号,以防文件名中包含空格,并且转义的分号表示已执行命令的结尾。


您是否有有关-exec行为的文档,该文档还解释了printf格式的占位符?
丹尼尔·贝克

不。脑子屁:我当时以为%p和%f是发现的东西,而不是printf的东西。我已投票支持您的答案。
兰迪·奥里森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.