使用特定名称递归重命名文件夹

使用特定名称递归重命名文件夹

我在 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_GHdirname命令将只输出/a path/to/some/random dir。然后我们/VT GH向其中添加我们想要的新名称,并将所有内容括在双引号中,同样是为了避免空格。

-n -T命令的参数告诉它,如果同一目录中mv已经存在VT GH与之关联的文件夹,则不要执行任何操作。在这种情况下,将保持不变。VT_GHVT_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出现在 和 之间testmv则代码将出现错误。如果 newVT GH是一个目录或指向目录的符号链接,mv则将移动VT_GH到 的内部VT GH(其中VT_GH可能已经存在另一个目录,因此mv -i)。如果 new VT GH不是目录,则不会被覆盖(即使您在mv -i提示时同意覆盖,情况也是如此;您将从 获得cannot overwrite non-directory with directorymv。考虑mv -n -T(如果支持,则选项不可移植)。
  • 执行的一般测试和操作find容易出现 TOCTOU。例如,目录可能VT_GH通过,-type d但执行时却出现mv常规文件。VT_GH
  • -print(或printf在 shell 中)只是为了通知您哪些目录已被更改。
  • find-sh解释如下:中的第二个 sh 是什么sh -c 'some shell code' sh
  • 如果testprintf是内置函数,sh那么第二种形式实际上可能更快。第一种形式不会生成,sh但它会为test每个目录生成一个进程VT_GH。第二种形式可能会生成多个sh进程,但每个sh进程处理许多目录并为您节省许多test进程。

相关内容