2013-11-05 45 views
1

我发现有几个类似的问题有解决方案,只是它们不涉及变量。使用替换和变量重命名文件和目录

我在文件和目录的树中有特定的模式 - 模式是单词模板。我想要一个脚本文件来重命名所有的文件和目录,用变量$ {newName}

中包含的一些其他名称替换单词TEMPLATE如果我知道$ {newName}的值是“弗雷德住在这里”,然后在命令

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}}"' {} \; 

然后Word模板由n代替ULL而不是“弗雷德住在这里”

我需要的“”大约$ 0,因为有在路径名称空间,所以我不能做这样的事情:

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

谁能帮助我得到这个脚本工作,使得包含Word模板的所有文件和目录都模板代替任何的${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

+0

你不想'$ 0'这些表达式。 '$ 0'的值是正在运行的程序,'bash -c'脚本的值是'bash''。 你正在使用哪种类型的系统?我会寻找'rename'命令并利用它。 –

+0

@Mark Reed。我不认为_rename_命令可以做目录。至少我不能让它工作 - 我确实尝试过。尽管* 0 *不是正确的,它的工作原理,所以我会坚持下去。 – rednectar

回答

1

你有两个选择。

1)最简单的解决方案是export newName。如果您不导出变量,那么它不可用于子壳中,并且bash -c是一个子壳。这就是为什么你将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" \; 
+0

出口建议很好,但没有告诉我该怎么做。 (感谢cforbish,尽管)。我尝试了两种选择: 第一个导致嵌入引号的新名称 - 如 /foo/bar /一些“Fred住在这里”目录/带有文件 第二个选项在名称中嵌入反斜杠字符\所以我结束了这些名字如: /foo/bar /一些Fred \ lives \ Here目录/带有文件 – rednectar

+0

@rednectar:yup,对不起。在两个命令行中都有额外的引号;我删除了它们。 ('export newName' * *是*如何导出newName;您可以在之前,在cforbish的示例中 - 或者在您设置其值之后执行此操作。一旦将变量标记为导出,它将保持该方式即使你重新分配了变量的值,对不起,假设这是显而易见的。) – rici

+0

修正后的第一个选项现在可用(使用'$ 0'的那个)。 'printf'版本不会重命名任何东西。 – rednectar

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 
+0

导出选项是缺失的链接 - 谢谢你,那个但是for循环没有起作用 - 变量文件没有选择整个路径/文件名,只有路径中的第一个空格。 [能够有足够业力的人投票回答这个问题吗?] – rednectar

+0

Did出口'find'方法d为你工作?如果你修改上一个脚本中的'mv'命令为'echo',它说什么? – cforbish

+0

如果在'mv'前面加上'echo',我会得到如下输出: 'mv ./foo/bar/some TEMPLATE directory/with files/foo/bar /一些Fred住在这里directory/with files' - I猜测我需要引用它来摆脱空间,或者通过额外的过程来摆脱空间。无论如何 - 'export newName =“Fred住在这里”'像一个魅力一样工作,所以问题解决了(尽管别人说我不应该使用$ 0)。 – rednectar