我find
使用以下命令在文件结构(数百个文件夹,大约 4 层深)上运行find "/media/$disk/_all" -depth -type d -exec/execdir rename -d 's/ 1000k/ [1000k]/' "{}" \;
:我反复指出,某些包含 1000k 的文件夹仍未重命名,我注意到其中一些在第二次运行该命令时被重命名。为什么不全部都在第一次运行呢?
另外,我注意到输出经常有“无法重命名/media/some_original /media/some_renamed:没有这样的文件或目录”,之后我检查,some_original 成功重命名为 some_renamed。
我猜测的第一个错误是由于 find 没有遍历所有树而发生的,第二个错误是由于 find 对某些/全部树进行并调用 exec 两次?条目。我后来添加了 -depth 选项,以确保“子”文件夹在“父”文件夹之前被重命名,但它没有帮助(在我的情况下,当我注意到错误时,我没有注意到由于被重命名而导致的几个级别)。
我无法通过网络搜索找到答案。这里可能有什么问题?
系统是Linux Mint 20.1。
添加:我已经检查过,使用 ls -lR /path/to/folder | 在结构中没有找到任何链接grep ^l 来自https://stackoverflow.com/questions/8513133/how-do-i-find-all-of-the-symlinks-in-a-directory-tree。
磁盘安装方式如下:输入 ext4 (rw,nosuid,nodev,relatime,stripe=8191,uhelper=udisks2)
答案1
初步说明
这个答案是试图解释可能发生的事情,而不是对确实发生的事情做出明确的解释。这是因为:
- OP 尝试了该命令的不同变体(带或不带
-depth
、带-exec
或-execdir
),问题正文中发布的确切命令应持保留态度; - 每次尝试都可能修改目录树,但没有日志说明由于确切的命令而发生的重命名;
- 同样,没有错误日志;
- 在分析问题(在评论和聊天中)后,我们注意到很少有不同的问题会生成类似的错误消息(因此很容易假设只有一个问题)。
由于这些原因,尝试创建一个单一的MCVE(以一个精确的目录树和一个精确的命令的形式
find
)失败。我们一致认为,最好是创建一个涵盖可能问题的答案,并考虑到未来的读者。这个答案就是这样的答案。- OP 尝试了该命令的不同变体(带或不带
有超过一个
rename
。所讨论的语法适用于rename
与 Larry Wall 和 Robin Barker 相关的 Perl 脚本。我认为这是rename
使用过的。不过,本答案中涵盖的问题并不特定于此rename
。
可能发生了什么
No such file or directory
当您使用 时,find
可能会产生一些不同的问题rename
。
首先,我们来简化一下这个例子。设目录结构为:
/a/b/c.1/c.2/d
命令是:
find /a/b -exec rename s/c/X/ {} \;
该命令将产生:
find: '/a/b/c.1': No such file or directory
这是因为在尝试下降到 之前没有-depth
find
进程。处理时,将其重命名为,但不知道名称更改。它尝试处理更深层次的文件,但已不存在。这非常类似于c.1
c.2
c.1
rename
X.1
find
c.1
c.1
find
与使用rm -r
。
该命令的第二次迭代将看到/a/b/X.1/c.2/d
并成功重命名c.2
为X.2
.尽管如此,它还是会抱怨c.2
不在那里。第三次迭代将不执行任何操作,也不抱怨任何内容。
在对目录本身执行任何操作之前,您需要告诉find
处理目录中的文件。这就是-depth
目的。
即使-depth
有了也可能仍然存在问题。再次,具有以下结构:
/a/b/c.1/c.2/d
并运行“固定”命令:
find /a/b -depth -exec rename s/c/X/ {} \;
我们将得到:
Can't rename /a/b/c.1/c.2/d /a/b/X.1/c.2/d: No such file or directory
Can't rename /a/b/c.1/c.2 /a/b/X.1/c.2: No such file or directory
这些消息的来源并不明显,rename
但确实如此。问题d
先处理一下,rename
想/a/b/c.1/c.2/d
改成/a/b/X.1/c.2/d
。就像,如果不存在,mv /a/b/c.1/c.2/d /a/b/X.1/c.2/d
你就不能这样做。/a/b/X.1/c.2/
稍后(在处理时c.2
)你不能,mv /a/b/c.1/c.2 /a/b/X.1/c.2
因为X.1
它还不存在。
(默认情况下,您可能会惊讶rename
地尝试某些无法成功的操作。注意,当不存在时,该命令mv /a/b/c.1/c.2/d /a/b/X.1/c.2/d
不会成功。当已经存在时,此命令仍然是正常的。在这种情况下, 的默认行为同样正常。)X.1
X.1/c.2/
c.1/c.2/
rename
在我们的例子中,X.1
出现了whenc.2
被默默地重命名为,X.1
但这发生在稍后。该命令的第二次迭代将在处理时抱怨d
,它将设法重命名c.2
。第三次迭代将不执行任何操作,也不抱怨任何内容。
请注意,如果您使用了/c.0
not/a
且命令为no find /c.0/b …
,则 norename
将会成功,并且任何次数的迭代都将是徒劳的。
问题是rename s/c/X/
尝试更改c
路径中的第一个,即使这c
是在目录组件中,而不是在文件名中。至少有两种方法可以解决这个问题。
您可以使用rename -d
。此选项rename
仅对文件名起作用。以下命令:
find /c.0/b -depth -exec rename -d s/c/X/ {} \;
将成功更改/c.0/b/c.1/c.2/d
为/c.0/b/X.1/X.2/d
(因此即使c.0
不是问题)。
-d
是一个相对较新的选择。一般来说,您rename
可能不支持它。在这种情况下,使用-execdir
而不是-exec
:
find /c.0/b -depth -execdir rename s/c/X/ {} \;
(一般来说,您find
可能支持也可能不支持-execdir
。)
它之所以有效,是因为在处理时d
,字符串rename
处理的是 now ./d
,而不是/c.0/b/c.1/c.2/d
;同样,处理时c.2
,是./c.2
,不是/c.0/b/c.1/c.2
。该工具每次都在各自的父目录中工作,因此相对路径有效。通过不在字符串中包含完整路径,我们得到rename -d
without的行为-d
。
嗯,差不多了。如果您想rename
用点做某事(例如更改c.2
为等),那么或c-2
中的前导点就是您需要处理的内容。 with就不存在这样的问题,无论你使用或;所以如果可以的话就使用。./d
./c.2
-d
-exec
-execdir
rename -d
最后说明
有问题的命令包括-depth
和rename -d
。 OP 明确指出:
我
-depth
后来添加了选项[...]
所以可能缺乏-depth
是最初的问题。但是之后:
[添加
-detph
]没有帮助
考虑到这一点并注意到错误 ( Can't rename …
) 来自rename
,我得出的结论-d
是并不总是存在或者我遗漏了一些东西。现在我认为find -depth
withrename -d
应该是稳健的。假设OP真的失败了,我还无法解释这一点。