无法将 ./test 移动到其自身的子目录“./test/test”

无法将 ./test 移动到其自身的子目录“./test/test”

当尝试将某些文件转换为小写时,我注意到一些对我来说很奇怪的事情。

在 bash 中执行此操作时:

find . -iname 'test' | while IFS='\n' read item; do mv $item $(echo $item | tr [:upper:] [:lower:]); done

并且 mv 的源和目标没有改变,我收到以下错误:

mv: cannot move '.test' to a subdirectory of itself, './test/test'

这个是./test/test从哪里来的?当回显而不是执行 mv 时,我得到的是mv ./test ./test。我在 FreeBSD 10 和 Debian 8.2.0 上都测试了这一点,结果相同。我遗漏了什么?

答案1

如果名称已经是小写,则会将其提供给 mv 命令两次,正如您所见。

如果 mv 的最后一个参数是一个目录,它将被视为所有其他命名实体应移动到的目标目录。

mv test test首先会检查最后一个参数是否存在,如果存在,则检查它是否为目录。在本例中是的,因此 mv 会检查它是否是同一个挂载点(如果不是,即目标是不同的设备,则需要复制文件然后删除原始文件);在本例中是的。因此 mv 构造了一个系统调用序列rename(2),将所有源名称依次附加到指定为目标的目录中:mv a b c d/将生成rename("a", "d/a")rename("b", "d/b")rename("c", "d/c")- 因此当然mv test test会尝试调用rename("test", "test/test");。这显然是一个错误,您不能将目录移动到其自身内部。

要解决您的问题,请将 mv 命令设置为新名称不同且不存在的条件(如果您有两个不同的文件,分别名为“Test”和“test”,您可能不想在未经询问的情况下替换第二个文件)。我没有对此进行测试,也没有在手机上输入它,它看起来会像这样:(new="$(echo "$old" | tr ...)"; [[ $new != $old && ! -e $new ]] && mv "$old" "$new"注意引号,您不希望名称中的空格给您带来隐喻性的楔子)。

相关内容