我对 bash 脚本编写还很陌生。我正在尝试编写一行来搜索具有特定名称的所有文件,并重命名它们,当前正在运行的脚本除外。
这是我目前所拥有的:
find $1 -name thescript.sh -exec /bin/bash -c 'test \'"$(readlink -f "$0")" = {}\' || mv {} \$\(dirname {}\)/thescript0.sh' \; || true
这里简要解释一下它在我脑海中是如何工作的:
- 使用
readlink
确定当前运行脚本的绝对路径 - 对于所有文件
{}
名为thescript.sh
在$1
的某个子目录中:- 测试生成的绝对路径是否等于文件
{}
- 如果测试失败(即它们不相等):
- 确定文件的目录
{}
- 移动文件
{}
到同一目录下但名称为thescript0.sh
的文件
- 确定文件的目录
- 测试生成的绝对路径是否等于文件
- 总是返回真
一些注意事项:
-
$1
脚本的第一个参数是重命名的基本目录 - 因为我想在
||
中使用“或”(exec
)子句,我遵循了对 this question 的一些回答并使用引用的命令启动了一个新的 shell,我可以在其中使用||
,这样 shell 就不会认为这个运算符是父命令的一部分。引用的命令从test
开始结束于thescript0.sh
-
readlink
在子 shell 中,因为readlink
的结果传递给test
- 我对
test
使用了转义引号因为否则我认为 shell 会认为第一个引号实际上是前一个单引号的终止符(它启动了引用的命令) - 我也逃脱了 subshell,不确定这是否正确(我还没有做到这一点),因为我希望 subshell 根据
find
的输出作为引用命令的一部分执行。 , 而不是在开始时执行(当它还没有输出可以处理时) - 如果测试失败(在大多数情况下是预期的),那么我不希望整个命令返回 false(不确定是否会),所以这就是我输入
|| true
的原因最后
我得到的错误是:
line 15: unexpected EOF while looking for matching `''
目前我找不到任何不匹配的报价;只有一对未转义的引号。
最佳答案
单引号不接受任何转义序列,甚至 \'
也不接受。要在单引号字符串中包含单引号,您必须离开并重新输入:
echo 'What'"'"'s wrong?'
echo 'Oh, it'\''s nothing.'
补充说明:
$0
不会在单引号内展开。find
的退出代码与-exec
的结果无关,所以||不需要 true
。为了最大程度的安全,最好将
{}
作为参数传递给 bash,而不是将其嵌入脚本中。这样空格和其他特殊字符就不会绊倒 bash。始终引用变量扩展以防它们包含空格或通配符。
考虑到以上所有因素,我推荐的更新:
find "$1" -name thescript.sh -exec bash -c 'test "$1" == "$2" || mv "$2" "$(dirname "$2")"/thescript0.sh' bash "$(readlink -f "$0")" {} \;
(我还没有测试过,所以希望你能理解要点,即使我打错了一些字。)
关于linux - 如果不是当前文件,则重命名文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48430892/