使用替换和变量重命名文件和目录

时间:2013-11-05 03:50:59

标签: bash file directory batch-rename string-substitution

我发现了几个有解决方案的类似问题,除了它们不涉及变量。

我在文件和目录树中有一个特定的模式 - 模式是TEMPLATE这个词。我想要一个脚本文件来重命名所有文件和目录,方法是将TEMPLATE替换为变量$ {newName}

中包含的其他名称。

如果我知道$ {newName}的值是“Fred住在这里”,那么命令

find . -name '*TEMPLATE*' -exec bash -c 'mv "$0" "${0/TEMPLATE/Fred lives here}"' {} \;

将完成这项工作

但是,如果我的脚本是:

newName="Fred lives here"
find . -name '*TEMPLATE*' -exec bash -c 'mv "$0" "${0/TEMPLATE/${newName}}"' {} \;

然后单词TEMPLATE被替换为null而不是“Fred住在这里”

我需要大约$ 0的“”,因为路径名中有空格,所以我做不了类似的事情:

find . -name '*TEMPLATE*' -exec bash -c 'mv "$0" "${0/TEMPLATE/"${newName}"}"' {} \;

任何人都可以帮助我让这个脚本工作,以便包含TEMPLATE一词的所有文件和目录都将TEMPLATE替换为${newName}的值

例如,如果newName="A different name"和我的目录是

/foo/bar/some TEMPLATE directory/with files然后该目录将重命名为

/foo/bar/some A different name directory/with files

,名为some TEMPLATE file的文件将重命名为

some A different name file

2 个答案:

答案 0 :(得分:2)

您必须使用IFS=$'\n'引号,因为bash -c是子shell,所以需要export任何变量。这有效:

#!/bin/bash
IFS=$'\n'
export newName="Fred lives here"
find . -name '*TEMPLATE*' -exec bash -c 'mv "$0" "${0/TEMPLATE/${newName}}"' {} \;

如果您不介意另外两行,并希望脚本更易于阅读(无需导出):

#!/bin/bash
IFS=$'\n'
newName="Fred lives here"
for file in $(find . -name '*TEMPLATE*'); do
    mv ${file} ${file/TEMPLATE/${newName}}
done

答案 1 :(得分:1)

您有两种选择。

1)最简单的解决方案是export newName。如果您不导出变量,那么它在子shell中不可用,bash -c是子shell。这就是为什么你将TEMPLATE替换为什么。

2)或者,您可以尝试构造一个包含$newName替换的正确引用命令行。如果您知道$newName表现得相当好(例如没有双引号或美元符号),那么很容易:

find . -name '*TEMPLATE*' \
       -exec bash -c 'mv "$0" "${0/TEMPLATE/'"${newName}"'}"' {} \;

(注意:bash引用充满了细微之处。以下内容经过多次编辑,但我认为现在是正确的。)

但是,由于您不能指望它,可能需要通过将文件名和替换替换为命令行参数来构造命令行。但在我们这样做之前,让我们修复$0。您不应该使用$0作为参数。正确的语法是:

bash -c '...$1...$1...' bash "argument"

请注意额外bash(许多人更喜欢使用_);它可以为子流程提供合理的名称。

考虑到这一点:

find . -name '*TEMPLATE*' \
       -exec bash -c 'mv "$1" "${1/TEMPLATE/$2}"' bash {} "$newName" \;