bash Linux-大规模文件夹重命名

bash Linux-大规模文件夹重命名,linux,bash,rename,Linux,Bash,Rename,在我们的Linux文件服务器(RedHat Enterprise)上,我们有一些需要重命名的文件夹,其中包含客户端工作。旧文件夹格式(需要更改的)是clientcode\u jobnumberjobname。新格式为clientcode\u jobnumber\u jobname。我们基本上需要通过在jobnumber和jobname之间的foldername中添加额外的下划线来更改旧文件夹名称。我们还将创建所有新的文件夹结构,以便以新格式显示,因此无需更改这些结构。作业编号始终为1个字母后跟4

在我们的Linux文件服务器(RedHat Enterprise)上,我们有一些需要重命名的文件夹,其中包含客户端工作。旧文件夹格式(需要更改的)是
clientcode\u jobnumberjobname
。新格式为
clientcode\u jobnumber\u jobname
。我们基本上需要通过在
jobnumber
jobname
之间的foldername中添加额外的下划线来更改旧文件夹名称。我们还将创建所有新的文件夹结构,以便以新格式显示,因此无需更改这些结构。作业编号始终为1个字母后跟4个数字。客户代码为3-4个字母,具体取决于客户。每个作业的作业名称都不同。这些文件夹都位于需要重命名的
clients/clientname/jobs/clientcode/“文件夹”
(这只是脚本必须深入结构的一个示例)。它需要为每个客户端下的每个
clientcode
执行此操作。如何设置脚本来执行此操作?任何帮助都将不胜感激。我们有数千个需要重命名的文件夹。

有几个命令的作用类似于文件名上的sed;尝试
mmv
(或
rename
的perl变体,也称为prename或rename.PL,您可能在RHEL上找不到)


作为奖励,两者都有一个
-n
选项(无act),这样您就可以检查您要做的事情不会破坏东西或丢失信息。

有几个命令的作用类似于对文件名使用sed;尝试
mmv
(或
rename
的perl变体,也称为prename或rename.PL,您可能在RHEL上找不到)

for entry in * ; do
  if [ ! -d "$entry" ] ; then
    continue
  fi
  jobname="${entry##*_?????}"
  dirbase="${entry%$jobname}"
  if [ -z "$dirbase" -o -z "$jobname" ] ; then
    echo "Error with '$entry'"
    continue
  fi
  mv "$entry" "${dirbase}_$jobname"
done

作为奖励,两者都有一个
-n
选项(无act),因此您可以检查您将要做的事情不会破坏东西或丢失信息。

可能只是我自己,但我不太清楚目录结构到底是什么样子,请您在一些代码标记中提供一个示例

for entry in * ; do
  if [ ! -d "$entry" ] ; then
    continue
  fi
  jobname="${entry##*_?????}"
  dirbase="${entry%$jobname}"
  if [ -z "$dirbase" -o -z "$jobname" ] ; then
    echo "Error with '$entry'"
    continue
  fi
  mv "$entry" "${dirbase}_$jobname"
done
也许这应该出现在serverfault.com上(但我想#!/bin/sh脚本算是编程)


编辑:新易卜拉欣,反抗?这是关于使用一种可以跨所有POSIX兼容版本工作的方法,或者Linux,也许我是老版本,但我拥有的Solaris机器不包括
rename
mmv
。因此,这样的解决方案是不可能的。

也许只有我一个人,但我不太清楚目录结构到底是什么样子,请您在一些代码标记中提供一个示例

也许这应该出现在serverfault.com上(但我想#!/bin/sh脚本算是编程)


编辑:新易卜拉欣,反抗?这是关于使用一种可以跨所有POSIX兼容版本工作的方法,或者Linux,也许我是老版本,但我拥有的Solaris机器不包括
rename
mmv
。因此,这样的解决方案是不可能的。

由于您说名称格式是高度结构化的,并且所有内容都在单亲(作为直接或间接子项..根据您所提到的内容不确定),我建议:

为文件夹名创建一个正则表达式,并编写一个小的perl脚本,该脚本将目标文件夹(在该文件夹下有要重命名的文件夹)的内容名与正则表达式相匹配。找到匹配项后,将文件夹重命名为新名称。Perl使这一切变得简单

如果您决定采用这种方法,只是为了以防万一,您不懂Perl,不知道从哪里开始,如果您有兴趣在此过程中进行一些学习,我建议您通读“Minimal Perl”一书…这是一种快速而有趣的学习这种可怕语言的方法,并将其用于与您现在需要的类似的事情


希望这能有所帮助。

既然你说名字的格式是高度结构化的,而且所有的东西都是单亲的(无论是直接的还是间接的孩子..从你提到的不确定),我建议:

find /path/clients -type d -name "*_?[0-9][0-9][0-9][0-9]*" | while IFS= read -r DIR
do
    dir=${DIR##*/}
    base=${DIR%/*}
    IFS="_"
    set -- $dir
    front=$1
    back=$2
    jobname=${back#?????}
    jobnum=${back%$jobname}
    newname="${front}_${jobnum}_${jobname}"
    echo mv "$DIR" "$base/$newname"
done
为文件夹名创建一个正则表达式,并编写一个小的perl脚本,该脚本将目标文件夹(在该文件夹下有要重命名的文件夹)的内容名与正则表达式相匹配。找到匹配项后,将文件夹重命名为新名称。Perl使这一切变得简单

如果您决定采用这种方法,只是为了以防万一,您不懂Perl,不知道从哪里开始,如果您有兴趣在此过程中进行一些学习,我建议您通读“Minimal Perl”一书…这是一种快速而有趣的学习这种可怕语言的方法,并将其用于与您现在需要的类似的事情


希望这能有所帮助。

RH重命名与Debian重命名不同,在这里不起作用。它有时被称为
prename
。注意:至少有两种完全不同的“重命名”,而Red Hat附带的一种“重命名”会在没有警告的情况下覆盖现有文件。Larry Wall基于perl的版本不会这样做(Ubuntu附带)。额外奖励:
vidir
,debian/ubuntu上的
moreutils
的一部分。RH重命名与debian重命名不同,在这里不起作用。它有时被称为
prename
。注意:至少有两种完全不同的“重命名”,其中一种带有红帽的“重命名”会在没有警告的情况下覆盖现有文件。Larry Wall基于perl的版本不会这样做(Ubuntu附带)。奖金:
vidir
,是debian/ubuntu上的
moreutils
的一部分。
find /path/clients -type d -name "*_?[0-9][0-9][0-9][0-9]*" | while IFS= read -r DIR
do
    dir=${DIR##*/}
    base=${DIR%/*}
    IFS="_"
    set -- $dir
    front=$1
    back=$2
    jobname=${back#?????}
    jobnum=${back%$jobname}
    newname="${front}_${jobnum}_${jobname}"
    echo mv "$DIR" "$base/$newname"
done