我在 Linux 磁盘上有一堆文件夹需要重命名。
文件夹名称如下
VT_GH
我想将每个名为 VT_GH 的文件夹重命名为 VT GH
我只想恢复具有该确切名称的文件夹。本质上是在系统上递归地用空格替换该文件夹名称中的下划线。这些文件夹大约有 50,000 个。
它在 RHEL7 上并且可以以 root 身份运行。
答案1
看起来有点复杂,但应该可以解决问题:
find / -depth -type d -name VT_GH -print | awk '{ print "mv -n -T \"" $0 "\" \"`dirname '"'"'" $0 "'"'"'`/VT GH\"" }' | bash
让我们把它分解成几个部分。第一个命令:
find / -depth -type d -name VT_GH -print
输出系统上名为 VT_GH 的所有文件夹的路径名列表。-depth
这里的参数很重要,因为它会使路径按从最深层开始的顺序列出。这在我们稍后重命名它们时很重要,因为如果我们有这样的路径/some/dir/VT_GH/VT_GH
,那么必须在重命名上层路径之前重命名下层路径VT_GH
,否则下层路径的路径将不复存在。
第二条命令:
awk '{ print "mv -n -T \"" $0 "\" \"`dirname '"'"'" $0 "'"'"'`/VT GH\"" }'
将此列表转换为命令列表mv
,其中每个命令的形式为:
mv -n -T "/a path/to/some/random dir/VT_GH" "`dirname '/a path/to/some/random dir/VT_GH'`/VT GH"
每个命令的第一个参数mv
是源目录的路径,用双引号括起来以防止目录名中可能出现的空格(如“a path”和“random dir”)。
第二个参数由两部分组成。第一部分是dirname
上面相同路径上调用的命令的输出(这次路径用单引号括起来,因为我们需要双引号来引用整个第二个参数)。因此,/a path/to/some/random dir/VT_GH
该dirname
命令将只输出/a path/to/some/random dir
。然后我们/VT GH
向其中添加我们想要的新名称,并将所有内容括在双引号中,同样是为了避免空格。
-n -T
命令的参数告诉它,如果同一目录中mv
已经存在VT GH
与之关联的文件夹,则不要执行任何操作。在这种情况下,将保持不变。VT_GH
VT_GH
此命令列表mv
仅作为输入提供bash
,这是此单行命令的最后一部分:)
答案2
如果你find
支持-execdir
(GNUfind
支持),那么这很简单:
find . -depth -type d -name VT_GH ! -execdir test -e 'VT GH' \; -execdir mv -i {} 'VT GH' \; -print
如果你find
不支持,-execdir
那么你需要它来运行一个或多个 shell 来操作路径。POSIX 解决方案可能是:
find . -depth -type d -name VT_GH -exec sh -c '
for f do
( cd "${f%/*}" && ! test -e "VT GH" && mv -i VT_GH "VT GH" && printf "%s\n" "$f" )
done
' find-sh {} +
笔记:
- 起点是
.
测试(我的意思是您可以创建一个测试目录并在其中进行测试)。您想要一个在系统上“递归”工作的解决方案,因此最终在代码中使用/
而不是.
。不过,最好至少排除/proc
、/dev
和/sys
。您可以明确排除它们或者给出比(可能有用)find
更具体的起点。/
-xdev
-depth
是为了防止find
进入不再存在的路径(比较这个答案;rm
或者mv
,同样的问题)。- 代码测试是否存在阻碍
VT GH
。但这仍然容易托克托。如果VT GH
出现在 和 之间test
,mv
则代码将出现错误。如果 newVT GH
是一个目录或指向目录的符号链接,mv
则将移动VT_GH
到 的内部VT GH
(其中VT_GH
可能已经存在另一个目录,因此mv -i
)。如果 newVT GH
不是目录,则不会被覆盖(即使您在mv -i
提示时同意覆盖,情况也是如此;您将从 获得cannot overwrite non-directory with directory
)mv
。考虑mv -n -T
(如果支持,则选项不可移植)。 - 执行的一般测试和操作
find
容易出现 TOCTOU。例如,目录可能VT_GH
通过,-type d
但执行时却出现mv
常规文件。VT_GH
-print
(或printf
在 shell 中)只是为了通知您哪些目录已被更改。find-sh
解释如下:中的第二个 sh 是什么sh -c 'some shell code' sh
?- 如果
test
和printf
是内置函数,sh
那么第二种形式实际上可能更快。第一种形式不会生成,sh
但它会为test
每个目录生成一个进程VT_GH
。第二种形式可能会生成多个sh
进程,但每个sh
进程处理许多目录并为您节省许多test
进程。