如果不是当前文件,则重命名文件

时间:2018-01-24 20:16:34

标签: linux bash shell

我对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
  • 始终返回true

一些注意事项:

  • $1脚本的第一个参数是重命名的基本目录
  • 因为我想使用"或" (||)在exec子句中,我跟随this question的一些答案并启动了一个带引号命令的新shell,在其中我可以使用||,以便shell并不认为这个运算符是父命令的一部分。引用的命令从test开始,以thescript0.sh
  • 结束
  • readlink位于子shell中,因为readlink的结果已传递给test
  • 我使用test的转义引号,否则我认为shell会认为第一个引号实际上是前一个单引号的终结符(它启动了引用的命令)
  • 我也逃过子shell,不确定这是否正确(我还没有那么远)因为我希望子shell作为引用命令的一部分执行,基于{{1}的输出},而不是在开始时执行(当它还没有输出工作时)
  • 如果测试失败(大多数情况下都会出现这种情况),那么我不希望整个命令返回false(不确定是否会这样),这就是我放find的原因最后

我得到的错误是:

|| true

我目前找不到任何不匹配的引号;只有一对未转义的引号。

1 个答案:

答案 0 :(得分:1)

单引号不接受任何转义序列,甚至不接受\'。要在单个带引号的字符串中包含单引号,您必须离开并重新输入:

echo 'What'"'"'s wrong?'
echo 'Oh, it'\''s nothing.'

附加说明:

  • $0不会在单引号内展开。

  • find的退出代码与-exec的结果无关,因此不需要|| true

  • 为了最大限度地提高安全性,最好将{}作为参数传递给bash,而不是将其嵌入脚本中。通过这种方式,空白和其他特殊角色不会绊倒。

  • 在包含空格或通配符的情况下,始终引用变量扩展。

考虑到以上所有因素的建议更新:

find "$1" -name thescript.sh -exec bash -c 'test "$1" == "$2" || mv "$2" "$(dirname "$2")"/thescript0.sh' bash "$(readlink -f "$0")" {} \;

(我还没有对它进行过测试,所以即使我做了一些拼写错误,也希望你得到主旨。)