【问题标题】:Use bash-type `${i%.mp3}` syntax with xargs?使用带有 xargs 的 bash 类型`${i%.mp3}` 语法?
【发布时间】:2010-10-08 14:41:12
【问题描述】:

使用示例(人为!):将 .mp3 文件重命名为 .txt。

我希望能够做类似的事情

find -name '*.mp3' -print0 | xargs -0 -I'file' mv file ${file%.mp3}.txt

这行不通,所以我将find 的输出通过sed -e 's/.mp3//g' 管道化,这样就行了。

虽然看起来有点骇人听闻; 有没有办法使用通常的 bash ${x%y} 语法?

【问题讨论】:

  • 您提出了一个问题,但没有纯粹的答案。或者至少是您愿意接受的答案,因为您从未检查过接受。我的“hackish”方式是管道find ... | sed ... | xargs ...。您将其作为替代方法。所以为了清楚地分解它,xargs 本身不支持 Bash 变量扩展。你能用很多不同的方法解决这个问题吗?如您所知,是的!你能在xargs 中“纯粹”这样做吗?不!

标签: bash syntax xargs


【解决方案1】:

不,xargs -0 -I'file' mv file ${file%.mp3}.txt 将不起作用,因为 file 变量将由 xargs 程序而不是 shell 扩展。其实将其称为变量并不完全正确,在xargs的手册中称为“replace-str”。

更新:如果只使用 xargs 和 bash(而不是 sed 或类似的),您当然可以让 xargs 启动一个 bash 进程,然后它可以做任何您想要的替换:

find -name '*.mp3' -print0 | xargs -0 bash -c \
'while [ -n "$1" ]; do mv "$1" "${1%.mp3}.txt" ; shift; done;' "bash"

【讨论】:

  • 在 xargs 执行它之前,有什么方法可以让 shell 扩展表达式?
  • “bash”的原因是它被解释为 $0,所以 $1 成为 xargs 输入的内容。
【解决方案2】:

如果您安装了 GNU Parallel:

find -name '*.mp3' -print0 | parallel -0 mv {} {.}.txt

如果您的文件名不包含 \n(换行符),这也可以:

find -name '*.mp3' | parallel mv {} {.}.txt

观看介绍视频以了解有关 GNU Parallel 的更多信息http://www.youtube.com/watch?v=OpaiGYxkSuQ

【讨论】:

    【解决方案3】:

    只是添加另一个建议,即使它不使用 shell 的替换机制,而是使用 sed 的。

    find -name '*.mp3' -print |
    sed -e 's/\.mp3$//' -e "s/.*/mv '&\.mp3' '&\.txt'/" |
    sh
    

    换句话说,为每个文件名创建一个mv 命令行,并将结果传递给sh

    如果任何文件的文件名中有撇号(单引号),这将失败。我发这篇文章主要是为了对抗“如果你只有 xargs,每个问题都会看起来像钉子”综合症。

    并非所有 sed 都具有完全相同的语法。特别是,我不能 100% 确定您可以在一些笨拙的旧 SunOS 上使用多个 -e 参数(在 /usr/ucb/blah/barf/vomit/xpg4/bin/sed 之类的东西中查找与 XPG 兼容的 sed)

    【讨论】:

    • 对于当代 Bash,当然。但它不能移植回真正旧的 Bash 版本,这里的 OP 可能会遇到这种情况,所以我试图使它合理便携。即使在 Heirloom sh 和其他类似的受累 shell 中,这也应该可以工作。
    【解决方案4】:
    find . -type f -name '*.mp3' | while read -r F
    do
      mv "$F" "${F%.mp3}.txt"
    done
    

    重击 4+

    shopt -s globstar
    shopt -s nullglob
    for file in **/*.mp3
    do
        mv "$file" "${file%.mp3}.txt"
    done
    

    【讨论】:

    • 我知道怎么做;问题的目的是看看是否可以使用 xargs 来执行此操作,并且不会立即扩展 replace-str(我猜)。
    【解决方案5】:
    perl rename.pl 's/\.mp3$/.txt/' *.mp3  
    # Or **/*.mp3 for zsh and bash with specific settings set, for a recursive 
    # rename.
    

    http://people.sc.fsu.edu/~jburkardt/pl_src/rename/rename.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-16
      • 2011-07-08
      • 1970-01-01
      • 2017-12-02
      • 1970-01-01
      • 2021-09-06
      • 1970-01-01
      • 2015-10-16
      相关资源
      最近更新 更多