我发现了几个有解决方案的类似问题,除了它们不涉及变量。
我在文件和目录树中有一个特定的模式 - 模式是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
答案 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" \;