本文介绍一个批量在多个目录名前加数字的shell脚本。假设这个shell脚本的名称是digitname.sh。在实际开发工作中,一般会在常用的重要目录前加上数字。例如,将目录命名为“1-开发文档”、“2-部门文档”。这样命名有以下好处:文件管理器查看时,一般会先列出以数字开头的目录。当目录下有多个子目录时,不用滚动页面就可以看到这些重要的目录,方便查看。在目录名前面加上不同的数字,这些目录在文件管理器中的顺序就会相对固定。后续的新目录不会打乱这些目录的顺序。便于个人记忆。Linux下使用cd命令进入common目录时,只需要输入前面的数字,使用Tab键即可完成。可以避免切换输入法输入中文。或者当某些目录名的前几个字符相同时,可以避免输入多个字符来完成。下面介绍的digitname.sh脚本用于在目录名和文件名前添加数字和“-”字符。脚本支持的功能说明如下:使用-p选项在给定文件名前加一个数字,数字从1开始递增。使用-r选项去掉给定文件名前的数字以及数字后的“-”字符。提供此功能主要是为了重新排序指定的目录名称。例如,原12个目录的目录名分别以数字1~12为前缀。5号和9号开头的目录后面会被删除。那么剩余目录的编号顺序就不连贯了。如果要重新连接数字顺序,可以使用-r选项去掉目录名前面的数字,然后使用-p选项重命名。使用-i选项,将给定文件名前面的数字加1。使用-m选项根据给定的目录名称创建一个新目录,这将自动在目录名称前加上一个数字和一个“-”字符。数值为当前目录下最大的子目录名数加1。脚本代码列表digitname.sh脚本的具体代码如下。代码中大部分关键代码都做了详细的注释,方便阅读。本文后面还将提供一个参考调用示例,以帮助理解。#!/bin/bash#该脚本用于重命名给定的文件名并创建新目录。说明如下:#-在给定的文件名前加一个数字,数字会增加。#-删除所有给文件名前面的数字和数字后面的'-'字符。#-给给定文件名前面的数字加1。#-根据给定的目录名创建一个新目录,会自动在目录名前面加上#号和'-'字符。number值为当前目录下子目录名的最大个数加1。一个时间。支持的选项如下:-h:打印此帮助信息,然后退出脚本。-p:在给定的文件名前添加一个数字,数字将递增。例如,如果给定的文件名是abc,将对应的文件名重命名为1-a2-b3-c-r:去掉给定文件名前面的数字和数字后面的'-'字符例如,如果给定的文件名是1-a22-b333-c,分别重命名为abc。如果给定的文件名开头不符合'number-'的格式,则不处理。-i:把所有文件名前面的数字加1,重命名文件,比如给定的文件名是1-a22-b333-c,就会重命名为2-a23-b334-c分别.如果给定的文件名开头不符合'Number-'的格式,则不处理。-m:根据给定的目录名创建一个新的目录,并会自动在目录名前加上数字和'-'字符。number值为当前目录下子目录名的最大个数加1。dirname1...dirnamen:可选文件名参数对于-p/-r/-i参数,后面提供的参数为要处理的文件名参数。如果没有文件名参数,则默认使用当前目录下的子目录名。对于-m参数,后面提供的参数是要创建的目录名的后缀。实际创建的目录名称将在给定的目标中在目录名称参数前添加数字和'-'字符。<注意>:当提供-m选项时,后面必须提供目录名参数。注意-p是前缀的简写。-r是删除的简写。-i是increase-m的缩写,是mdkir的缩写。你可以按照这些词的意思来帮助记忆每个选项的作用。"}#这个函数重命名给定的每个文件名,并会在文件名前添加一个数字。数字从1开始#递增。对于例如,如果给定的文件名参数是abc,它将被重命名为1-a2-b3-c.prefix_digit_to_filename(){if[$#-eq0];thenecho"Usage:$FUNCNAMEfilename1[filename2...[filenamen]]"return1fi#文件名前面加的数字从1开始,如果需要可以改为从0开始。localnumber=1localfilenameforfilenamein"$@";do#不判断文件名是否以数字开头,直接在文件名前加数字mv-v"${filename}""$((number++))-${filename}"done}#这个函数重复命名每个给定的文件名会去掉文件名前面的数字和'-'字符。#比如给定的文件名参数是1-a22-b333-c,就会重命名到bc.remove_filename_prefix_digit(){if[$#-eq0];thenecho"Usage:$FUNCNAMEfilename1[filename2...[filenamen]]"return1fi#在Linux中,mv命令一次只能处理一个重命名的文件名。重命名命令#可以处理多个文件,可以用正则表达式来表示要替换的文件名的内容。#重命名命令使用perl正则表达式。您可以使用\d来匹配任何数字.#使用+匹配一个或多个前面的字符。然后^\d+匹配文件名开头的所有数字。#^\d+之后的-对应于'-'字符本身。它后面必须跟一个“-”字符。#以下命令将文件名开头的数字和'-'字符替换为空,从而删除数字。rename-v's/^\d+-//'"$@"}#这个函数重命名每个给定的文件名,会给给定文件名开头的数字加1。例如#给的文件名参数为1-a22-b333-c,则重命名为2-a23-b334-c.increase_filename_number(){if[$#-eq0];thenecho"Usage:$FUNCNAMEfilename1[filename2...[filenamen]]"return1fi#在perl的s///e表达式中,在末尾添加e指定求值表达式。如果#不在末尾加e,则只进行字符串拼接,不进行算术运算。用#括号把\d+括起来,这样就可以通过$1d+匹配内容反向引用到\。rename-v's/^(\d+)-/sprintf("%d-",$1+1)/e'"$@"}#根据给定的目录名创建一个新目录。目录名称前将添加数字,后跟#'-'字符。具体数值将从当前子目录名开头的最大数字开始递增。#例如当前目录下,编号最大的子目录名开头为333-c。调用该函数时,#传入目录名的参数为d,会新建一个334-d目录。mkdir_digit_filename(){如果[$#-eq0];thenecho"error:use-moption,稍后必须提供要创建的目录名。"return1fi#打开bash的extglobshell选项,然后在路径名扩展中使用#+(pattern-list)表示匹配给定模式一次或多次。这个选项的状态与#所在的shell有关。在当前shell中打开此选项而不影响父shell此选项的状态。#你可以使用shopt-pextglob查看这个选项的状态。它应该默认启用。#在这里主动开启这个选项,提高便携性,防止部分Linux版本不开启。shopt-sextglob#打开extglob选项后,+([0-9])-*/会扩展为当前目录下的子目录名,以#号开头,后面跟'-'字符,不包括文本文件名。#使用ls-d命令逐行打印扩展子目录名,传给awk处理。#awk用'-'分割给定的字符串,得到子目录名前面的数字,输出最大的数字。本地maxnumber=`ls-d+([0-9])-*/|\awk-F'-''{if(x<$1)x=$1}END{printx}'`localdirname#在每个给定的目录名前加上数字,并创建一个新目录。#目录名前面的数字将从当前子目录名开头的最大数字开始递增。对于“$@”中的目录名;domkdir-v"$((++maxnumber))-${dirname}"done}#如果给出的第一个选项参数是-h,则打印帮助信息,然后退出。不带#参数时,同样打印帮助信息,然后退出。要求至少提供一个参数.if["$1"=="-h"-o$#-eq0];thenshow_helpexit0fi#先保存第一个option参数的值,以免后面执行shift1后得到这个值.option_type="$1"#进行后续操作时,只需要提供除-h以外的一个option参数.#接下来用shift1去掉第一个option参数,剩下的都是文件名参数.shift1#给的参数个数等于0时,表示只提供option参数,不提供文件名参数提供。#默认使用*/通配符匹配当前目录下的子目录名。bash中的路径名#展开,*/的通配符表示只展开到子目录名。目前默认只处理#子目录名。如果要处理当前目录下的所有文件名,可以将*/更改为*.if[$#-eq0];thendirnames="*/"elsedirnames="$@"fi#为了使用*/通配符进行扩展,不要用双引号把${dir_list}括起来。if["$option_type"=="-p"];然后prefix_digit_to_filename${dirnames}elif["$option_type"=="-r"];然后remove_filename_prefix_digit${dirnames}elif["$option_type"=="-i"];然后increase_filename_number${dirnames}elif["$option_type"=="-m"];then#创建新目录时,目录名由用户提供,使用$@获取给定的目录名参数。mkdir_digit_filename"$@"elseecho"错误:不支持给出的第一个选项参数,请使用-h选项查看帮助信息。"exit2fiexit一个参考测试例子把digitname.sh脚本文件放到bashshell的当前工作目录下,添加可执行权限具体测试如下:$mkdirtestrename$cdtestrename[testrename]$mkdir1-a22-b333-c[testrename]$ls1-a22-b333-c[testrename]$./digitname.sh-r1-a/重命名为a/22-b/重命名为b/333-c/重命名为c/[testrename]$lsabc[testrename]$./digitname.sh-pab'a'->'1-a''b'->'2-b'[testrename]$ls1-a2-bc[testrename]$./digitname.sh-i2-b/2-b/重命名为3-b/[testrename]$ls1-a3-bc[testrename]$./digitname.sh-mcmkdir:createddirectory'4-c'[testrename]$ls1-a3-b4-cc上面的命令首先在当前工作目录。然后进入该目录,创建三个子目录1-a、22-b、333-c。执行./digitname.sh-r命令时,不带文件名参数,默认处理当前目录下的所有子目录。这里将1-a、22-b、333-c这三个子目录分别重命名为a、b、c。即去掉目录名前面的数字和'-'字符。执行./digitname.sh-pab命令,提供的文件名参数为ab。这会将目录a和b分别重命名为1-a和2-b。也就是说,在目录名称前加上一个数字和一个“-”字符。数字从1开始递增。执行./digitname.sh-i2-b/命令,将给定的2-b目录前面的数字加1,重命名为3-b。执行./digitname.sh-mc命令会将当前目录下最大子目录名的值加1到给定的目录名参数前面。当前目录下的子目录名最大数为3,加1后为4,创建4-c目录。注意:虽然当前目录下有一个名为c的目录,但是./digitname.sh-mc命令不会重命名c目录。相反,会创建一个新目录,目录名称后跟一个数字。测试结束后,可以执行以下命令删除创建的测试目录和文件:rm-rtestrename/
