【问题标题】:How to use xargs to run bash -c on filenames with both single and double quotes如何使用 xargs 对带有单引号和双引号的文件名运行 bash -c
【发布时间】:2021-11-30 23:50:51
【问题描述】:

我正在尝试使用 xargs 对文件夹中的每个文件运行 ffmpeg 并输出具有 vorbis 音频的文件的名称。

我想出了以下最有效的方法,但在文件名中包含单引号的文件上失败了。

find . -maxdepth 1 | onlyvideos | tr '\n' '\0' | xargs -n1 -0 -I '{}' bash -c "if ( ffmpeg -i '{}' 2>&1 | grep Stream | grep -q vorbis ) ; then echo '{}' ; fi;"

onlyvideos 是我编写的一个脚本,它只将带有视频扩展名的文件的名称打印到标准输出。

如何让xargs 对可能包含单引号和双引号的文件名运行bash -c

【问题讨论】:

  • 如果find 可以做到这一点,你为什么要使用自定义脚本onlyvideos
  • 另外你应该在使用xargs -0时将-print0添加到find
  • 因为我不想每次都手动列出它们:String[] videoextensions = {"avi", "bdmv", "divx", "flv", "m2ts", "m4v", "mkv", "mp4", "mpg", "mpls", "vob", "webm", "xvid"};。这与我的问题并不真正相关,但我发现我的脚本非常有用并且一直在使用它,除了我的 onlymusic 脚本。
  • @suleiman 是的。这也与我的问题无关,但我的 onlyvideos 脚本目前不支持空值作为分隔符。
  • 您是否尝试过从bash -c cmd 中删除双引号并改用$()

标签: bash escaping xargs


【解决方案1】:

所有这些都可以大大简化,但如果你想坚持使用你的 onlyvideos 脚本,你可以尝试:

find . -maxdepth 1 | onlyvideos | tr '\n' '\0' |
  xargs -n1 -0 bash -c 'if ( ffmpeg -i "$1" 2>&1 | grep Stream | grep -q vorbis ) ; then echo "$1" ; fi;' bash

解释:bash -c 'cmd' arg0 arg1 执行cmd,位置参数设置为$0=arg0(在我们的例子中是bash)和$1=arg1(在我们的例子中是文件名,由xargs 传递)。因此,在您的命令脚本中使用 "$1" 'cmd' 应该可以按预期工作。

【讨论】:

  • 太棒了!非常感谢。怎么可能简化,只是为了我的学习?只是对如何有帮助的一般解释。你的意思是我只能将find -print0 与实际的视频扩展一起使用,而不是onlyvideostr
  • 是的,例如。或者更好的是,编写一个新版本的 onlyvideos 脚本(例如,foo.sh),它接受一个参数,当且仅当它是一个带有 vorbis 音频的视频文件时才打印它。当然,您可以在这个新脚本中重复使用您的 onlyvideos 脚本。然后,只需将findexec 操作一起使用:find . -maxdepth 1 -exec ./foo.sh {} \;
【解决方案2】:

while 风格

find . -maxdepth 1 | onlyvideos | while read f; do if ( ffmpeg -i "$f" 2>&1 | grep Stream | grep -q vorbis ) ; then echo "$f" ; fi; done

【讨论】:

  • 非常棘手,似乎有不止一种方法可以给猫剥皮!谢谢你。这似乎也更具可读性。
  • 在使用它之前,您应该仔细检查您的文件名和onlyvideos 脚本。 while read f 不保留前导和尾随空格,解释反斜杠,将拆分包含换行符的名称...(请注意,基于 xargs 的解决方案还将拆分包含换行符的名称)。至少,保留tr 替换并使用while IFS= read -r -d'' 可能会更好。
  • @RenaudPacalet 感谢您提供有关while read f 的提示。我认为引号至少可以保护前导和尾随空格。仅仅为了逃避,Bash 似乎过于复杂和危险。这么多的陷阱和边缘案例。如果您愿意,如果您可以声明强类型变量,那就太好了。
猜你喜欢
  • 2013-12-05
  • 2013-02-24
  • 1970-01-01
  • 2016-01-22
  • 1970-01-01
  • 2021-08-29
相关资源
最近更新 更多