这个文件重命名循环有什么问题?

时间:2018-03-11 01:51:19

标签: bash loops redirect pipe

我试图遍历目录中的所有文件,并使用下面的命令将它们从前缀ABC重命名为XYZ

while read file; do mv \"$file\" \"$(echo $file | sed -e s/ABC/XYZ/g)\" ; done < <(ls -1)

当我在mv前面抛出一个回声时,一切看起来应该可以正常工作并且复制/粘贴输出的命令工作正常但它不能在循环给定的上下文中正确执行一个使用错误,好像命令是如下所示。

usage: mv [-f | -i | -n] [-v] source target
       mv [-f | -i | -n] [-v] source ... directory

即使使用echo检查输出的命令

mv "ABC Test1" "XYZ Test1"

这应该是一个有效的命令,如果我复制粘贴,则有效。

知道发生了什么事吗?

2 个答案:

答案 0 :(得分:2)

Relace:

while read file; do mv \"$file\" \"$(echo $file | sed -e s/ABC/XYZ/g)\" ; done < <(ls -1)

使用:

for file in *
do
    mv "$file" "${file//ABC/XYZ}"
done

注意:

  1. 这非常重要:Never parse ls. ls仅用于生成人性化的输出。

  2. 要迭代目录中的所有文件,请使用for file in *; do ...; done。这将对所有文件名庄严可靠地工作,包括带换行符,空格或其他困难字符的文件名。

  3. \"生成一个文字字符,而不是句法字符。由于我们想要"的句法含义,我们将其保留为未转义状态。

  4. 有时需要sed,但这不是其中之一。 shell能够进行简单的替换,而不会出现与命令替换相关的所有问题。因此,$(echo $file | sed -e s/ABC/XYZ/g)可以替换为${file//ABC/XYZ}

    表单${var//old/new}称为模式替换,并在man bash中记录。

答案 1 :(得分:1)

非常愚蠢的错误。没有必要在mv命令中转义引号。把它们拿出来使它按预期工作。转义引号会显示带有echo的正确输出,但不会给出预期的行为。

while read file; do mv "$file" "$(echo $file | sed -e s/ABC/XYZ/g)" ; done < <(ls -1)