【问题标题】:Rename multiple files changing the extension and part of the string重命名多个文件,更改扩展名和部分字符串
【发布时间】:2017-12-24 06:27:35
【问题描述】:

我在一个目录中有*.new 文件的列表。这些文件的名称中包含 D1 将被替换为 D2 并且还必须将扩展名从 .new 删除为空

hello_world_D1_122.txt.new -------> hello_world_D2_122.txt

我尝试的是

ls -slt | grep -iE "*.new$" | awk -F " " '{print $10}' | xargs -I {} mv {} "echo {} | sed -e 's/.D1./.D2./g ; s/.new//g'"

此命令未产生所需的输出。上述命令的输出是

mv: rename hello_world_D1_122.txt.new to echo hello_world_D1_122.txt.new | sed -e 's/D1/D2/g ; s/.new//g': No such file or directory

【问题讨论】:

  • 它有什么作用?提供问题的示例输出。
  • 此命令将所有文件名转换为所需的文件名。例如:hello_world_D1_122.txt.new -------> hello_world_D2_122.txt
  • 嘿!好的。我的意思是你当前的命令是做什么的?
  • 您不会在控制台上看到任何内容,但是一旦处理了命令,就可以看到结果
  • 我的命令给了我这个输出。 mv: 将 hello_world_D1_122.txt.new 重命名为 echo hello_world_D1_122.txt.new | sed -e 's/D1/D2/g ; s/.new//g': 没有这样的文件或目录

标签: bash shell xargs


【解决方案1】:

为什么要使用一堆shell工具,你可以使用bash内置工具,使用参数扩展语法进行字符串操作

for file in *.new; do 
    [ -f "$file" ] || continue
    temp="${file%*.new}"
    mv -- "${file}" "${temp/D1/D2}"
done

"${file%*.new}" 部分从文件名中去除扩展名.new,"${temp/D1/D2}" 将D1 替换为D2

我不知道为什么要坚持使用 GNU xargs,但是您可以使用这种不可读的方式来实现这一点。使用printf列出以空为分隔符的文件,使用xargs -0以空为分隔符读取,

printf '%s\0' *.new | xargs -0 -r -I {} sh -c 'temp="${0%*.new}"; mv -- "${0}" "${temp/D1/D2}"' {}

【讨论】:

【解决方案2】:

除了明显的语法错误之外,您当前的尝试还包含大量问题。

参数"echo {} | sed '...'" 是一个文字字符串; xargs 无法将其解释为命令(尽管它当然会将 {} 替换为此字符串中的文件名)。

另外,don't use ls in scripts 如果你真的需要,使用ls -l 然后扔掉长格式是......只是愚蠢,效率低下,而且容易出错(详见链接) .

没有xargs:

for f in ./*.new; do
    [ -f "$f" ] || continue   # in case the glob matches no files
    d=${f%.new}               # trim off extension
    mv "$f" "${d/.D1./.D2.}"  # replace .D1. with .D2.
done

(我想您想替换文字点,尽管您的正则表达式将匹配除换行符之外的任何字符,后跟 D1 后跟除换行符之外的任何字符。)

如果您坚持使用xargs 解决方案,您可以将上述脚本包装在bash -c '...' 中并将其传递给xargs:

printf '%s\0' ./*.new | xargs -r0 bash -c 'for f; do d=${f%.new}; mv "$f" "${d/.D1./.D2.}"; done' _

【讨论】:

  • 这个网站上还有很多关于如何使用各种rename 命令的问题,其中一些可以很容易地做到这一点,它们的数量还没有超过已知宇宙中的原子数.
  • 看起来或多或少与我的相似(但不声称抄袭)++
  • 是的,刚刚看到你的更新——如果我没有将它从 cmets 引用到另一个答案,我会删除它。
【解决方案3】:

使用 GNU Parallel,它看起来像这样:

parallel mv {} '{=s/D1/D2/;s/.new//=}' ::: *.new

如果你有疯狂的文件名:

touch "$(printf "Shell  Special\n\n'*$!_D1_txt.new")"
parallel -0 mv {} '{=s/D1/D2/;s/.new//=}' ::: *.new

【讨论】:

    猜你喜欢
    • 2013-11-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-24
    • 1970-01-01
    • 2017-10-04
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    相关资源
    最近更新 更多