.bat脚本初体验——使用批处理bat清洗文件名

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_30239361/article/details/81703851

.bat脚本初体验——使用批处理bat清洗文件名

虽然说bat批处理脚本就是连续执行一条条DOS命令,相对于C语言等编程语言来说显得十分有限,但对多个文件进行批量操作是非常方便的。这篇文章旨在记录一下我无意中想到的使用bat的一个小实例。
对批处理和DOS命令熟悉的大神可以直接跳过。


使用场景

本人喜欢看电影,习惯了将电影在各大资源网站上面下载下来有空看看。下载下来的视频文件就会遇到下面这样的情况:
这里写图片描述
强迫症患者简直不能忍。。
但是文件夹里面有几百个视频文件,逐个逐个改对于程序员来说是不可接受的。
之前也尝试过使用python码一个脚本遍历文件然后去掉相关的广告字眼,但是毫无疑问这种情况批处理脚本更适合。


bat解决批量文件名清洗

直接上代码:

@echo off

REM MainProgrem
setlocal enabledelayedexpansion
set sum=0
for /r %%i in (.,*)do (
echo %%i
set old_string=%1
set new_string= 
echo %%i|findstr "!old_string!" >nul
if !errorlevel! equ 0 (
  echo 找到目标!
  call :getNewName %%i !old_string! !new_string!
  set /a sum+=1
)
)
echo 一共修改了!sum!个文件。
pause

:getNewName
set whole_string=%1
set old_char=%2
set new_char=%3
setlocal enabledelayedexpansion
for /f "tokens=*" %%i in ("%whole_string%") do (
set "var=%%i"
  if not !var!.==. (
    set "var=!var:%old_char%=%new_char%!"
    echo !var!>>newname.txt
  )
)
set /p newname=<newname.txt
call :changeFileName %1 %newname%
del newname.txt
goto :eof

:changeFileName
echo 将文件名:%1 改成:%2
move %1 %2
goto :eof

主要的思路就是:遍历当前目录的文件——寻找广告字符串——得出新的文件名——修改文件名。
当然这里面包含着很多bat的一些基本语法的使用,没有bat使用经验的人会处处碰壁,各种语法出错或者是达不到预期效果。下面是主要使用到的批处理知识要点:

  • echo与REM
    echo指的是回显输出。我们最常用的就是echo 【提示信息】,在屏幕上输出提示信息。
    我们可以使用echo on/echo off对当前的回显功能进行设置;
    直接输入echo可以查看当前的echo设置状态;

    REM是注释命令,该命令后的内容将不会被程序执行,但是能回显。
    平时也会使用::双冒号来更简洁地进行注释,与REM的区别在于::后面的字符在执行时不会回显,如论你是否执行echo on
    但是这里要注意的是冒号需要慎用,冒号后面紧跟一个以字母数字开头的字符串,我们称之为有效标号,是可以被callgoto语句识别的;而冒号后面紧跟一个非字母数字的特殊符号就成为无效标号,可以起到注释作用。

  • 重定向符
    重定向符号是bat脚本中使用非常频繁的特殊符号之一。有>、>>、<、>&、<&等。
    DOS的标准输入输出通常是在键盘和显示器上进行的,但是利用重定向可以方便地对磁盘文件和其他设备进行输入输出操作。
    输出重定向符>将命令发送到设备和文件当中,如echo hello word>test.txt,此处test.txt是新建一个文件并且写入心的内容,如果目录下已经有test.txt则覆盖掉之前的内容;而如果使用>>重定向的话,则不会覆盖以前的内容,而是将内容追加到原有文件的末尾处。
    需要注意的是,重定向符前面不需要加空格,不然该空格则被当成是输出的内容添加到文件或设备当中。

  • set语句
    set语句最大的作用就是对变量进行赋值。
    在批处理中,允许两类的变量存在——系统变量和自定义变量。
    系统变量有很多,是系统事先定义并且自动赋值的变量。如%DATE%、%HOMEPATH%等等。若想要知道系统变量的值我们可以在命令行中直接echo出来即可。另外,我们在使用批处理的参数0%~9%也属于系统变量。
    自定义变量即我们在编写bat脚本的过程中我们可以自由赋值的变量。
    set命令最常用的格式是SET [variable=[string]] ,就是很单纯地将一个值赋给一个值;set命令还有两种比较常用的参数形式/p和/a,它们的用法是SET /P variable=[promptString]SET /A variable=[expression]

REM 实例1:
@echo off  
set var=我是一个值  
echo %var%      ::在程序的其他位置要引用变量则需要用两个%括起来,这里回显一个字符串“我是一个值”
pause  

REM 实例2:
@echo off  
set /p var=请输入你的名字:   
echo 您的名字是:%var%        ::此时var变量接收到的值是用户自己输入的值
pause   

REM 实例3:
@echo off
set a=100
set b=1000
set /a c=a+b    ::变量c通过一个表达式来进行赋值
echo the result is :%c%
pause

REM 程序中:
set /p newname=<newname.txt     ::结合输入重定向符将文件newname.txt中的内容赋值给变量newname
  • find和findstr
    命令find可以在文件中搜索字符串,用法
    FIND [/V] [/C] [/N] [/I] [/OFF[LINE]] "string" [[drive:][path]filename[ ...]]
    /V 显示所有未包含指定字符串的行。
    /C 仅显示包含字符串的行数。
    /N 显示行号。
    /I 搜索字符串时忽略大小写。
    /OFF[LINE] 不要跳过具有脱机属性集的文件。
    “string” 指定要搜索的文字串,
    [drive:][path]filename 指定要搜索的文件。
    如果没有指定路径,FIND 将搜索键入的或者由另一命令产生的文字。
    Find常和type命令和管道符|结合使用:
    Type [drive:][path]filename | find "string" [>tmpfile] #挑选包含string的行
    Type [drive:][path]filename | find /v "string" #剔除文件中包含string的行
    Type [drive:][path]filename | find /c #显示文件行数
    以上用法将去除find命令自带的提示语(文件名提示)
    命令findstr同样也是搜索字符串,使用方法和参数设置更为复杂,详细的可以参看:
    https://blog.csdn.net/zhouzihan520xj/article/details/40301041

  • for循环
    for循环的基本格式:
    FOR %%variable IN (set) DO command [command-parameters]
    %variable 指定一个单一字母表示可替换的参数。
    (set) 指定一个或一组文件。可以使用通配符。
    command 指定对每个文件执行的命令。
    command-parameters 为特定命令指定参数或命令行开关。
    for循环有4个参数:/d、/l、/r、/f。
    参数/d主要用于遍历目录,不会遍历文件:
    FOR /D %%variable IN (set) DO command [command-parameters]
    参数/r可以遍历目录以及文件:
    FOR /R [[drive:]path] %%variable IN (set) DO command [command-parameters]
    参数/l可以遍历以增量形式从开始到结束的一个数字序列集:
    FOR /L %%variable IN (start,step,end) DO command [command-parameters]
    参数/f就比较复杂,使用文件解析来处理命令输出、字符串及文件内容。使用迭代变量定义要检查的内容或字符串,并使用各种options选项进一步修改解析方式。使用options令牌选项指定哪些令牌应该作为迭代变量传递。请注意:在没有使用令牌选项时,/F 将只检查第一个令牌。文件解析过程包括读取输出、字符串或文件内容,将其分成独立的文本行以及再将每行解析成零个或更多个令牌。然后通过设置为令牌的迭代变量值,调用 for 循环。默认情况下,/F传递每个文件每一行的第一个空白分隔符号。跳过空行。
    FOR /F ["options"] %%variable IN (file-set) DO command [command-parameters]
    FOR /F ["options"] %%variable IN ("string") DO command [command-parameters]
    FOR /F ["options"] %%variable IN ('command') DO command [command-parameters]
    带引号的字符串”options”包括一个或多个指定不同解析选项的关键字。这些关键字为:
    eol=c - 指一个行注释字符的结尾(就一个)(备注:默认以使用;号为行首字符的为注释行)
    skip=n - 指在文件开始时忽略的行数,(备注:最小为1,n可以大于文件的总行数,默认为1。)
    delims=xxx - 指分隔符集。这个替换了空格和跳格键的默认分隔符集。
    tokens=x,y,m-n - 指每行的哪一个符号被传递到每个迭代的 for 本身。这会导致额外变量名称的分配。m-n格式为一个范围。通过 nth 符号指定 mth。如果符号字符串中的最后一个字符星号,那么额外的变量将在最后一个符号解析之后分配并接受行的保留文本。经测试,该参数最多只能区分31个字段。(备注:默认为1,则表示只显示分割后的第一列的内容,最大是31,超过最大则无法表示)
    usebackq - 使用后引号(键盘上数字1左面的那个键)。
    未使用参数usebackq时:file-set表示文件,但不能含有空格;双引号表示字符串,即”string”;单引号表示执行命令,即’command’; 使用参数usebackq时:file-set和”file-set”都表示文件, 当文件路径或名称中有空格时,就可以用双引号括起来,单引号表示字符串,即’string’,后引号表示命令执行,即command。

REM 实例1:输出c盘下的所有目录名字
@echo off
for /d %%i in (c:\*) do echo %%i
pause

REM 实例2:输出c盘下的所有exe文件名字
@echo off
for /r c:\ %%i in (*.exe) do echo %%i
pause

REM 实例2:输出1~5
@echo off
for /l %%i in (1,1,5) do @echo %%i
pause

REM 实例3@echo off
rem 首先建立临时文件test.txt
echo ;注释行,这是临时文件,用完删除 >test.txt
echo 111213141516段 >>test.txt
echo 21段,22段,23段,24段,25段,26段 >>test.txt
echo 31段-32段-33段-34段-35段-36段 >>test.txt
FOR /F "eol=; tokens=1,3* delims=,- " %%i in (test.txt) do echo %%i %%j %%k
Pause
Del test.txt

运行显示结果:
1113141516212324段,25段,26313334段-35段-36段
请按任意键继续. . .
  • setlocal与变量延迟
    当我们使用到for循环并且在里面需要对变量进行动态赋值的时候,我们肯定要面临的问题就是变量延迟。这是由于批处理是按行读取命令这一机制导致的。在批处理对一行的命令进行执行之前,将会有一个预处理的过程,其中就包括了对命令中的变量进行赋值。
    我们可以使用setlocal enabledelayedexpansion来开启变量延迟,并且后续对需要延迟赋值的变量使用一对感叹号!!括起来。
    在程序中,对总数sum、传入子程序的old_stringnew_string以及getNewName中的var我们都需要设置变量延迟,否则将会由于赋值过程中出现问题,达不到预期的效果。
    使用实例如下:
REM 实例1:输出结果为4
@echo off
set a=4
set a=5 & echo %a%
pause

REM 实例2:输出结果为5
@echo off
setlocal enabledelayedexpansion
set a=4
set a=5 & echo !a!
pause 

REM 实例3:输出结果为五行,分别是1~5。如果不使用变量延迟,则会出现“ECHO处于关闭状态”的提示。
@echo off
setlocal enabledelayedexpansion
for /l %%i in (1,1,5) do (
set a=%%i
echo !a!
)
pause
  • if条件语句与errorlevel
    if是条件判断语句,语法格式:
    IF [NOT] ERRORLEVEL number command
    IF [NOT] string1 compare-op string2 command
    IF [NOT] EXIST filename command
    第一行用法中的errorlevel表示程序上一行命令的返回码,用于判断上一行命令是否执行成功。上面程序中的echo %%i|findstr "!old_string!" >nul意思就是在参数%%i中寻找是否存在字符串old_string,并且屏蔽了命令执行成功的信息。一般执行成功errorlever默认值为0,出错一般为1或者9009等其他正值。
    其中第二行用法中的compare-op包括:
    EQU - 等于
    NEQ - 不等于
    LSS - 小于
    LEQ - 小于或等于
    GTR - 大于
    GEQ - 大于或等于
    另外,加上参数[/I]则不考虑大小写。

  • call调用子程序
    Call命令可以在批处理中调用另一个批处理程序,并且在执行完该程序之后继续执行原来的批处理。
    CALL command直接执行一条命令。
    CALL [drive:][path]filename [batch-parameters]调用其他批处理程序,必须是.bat或者.cmd程序。
    CALL :label arguments调用本文件内的命令段,相当于子程序。被调用的子程序以:label开头,以goto :eof结尾。

  • 文件名修改命令
    bat中使用ren和move这两个命令对文件名进行修改。
    他们的区别在于使用ren命令修改文件名字时文件位置会保持在同一个文件夹目录下;move命令可以跨文件夹目录进行文件名修改:
    ren d:/test/oldname.txt newname.txt
    move d:/test/ouldname.txt e:/test/newname.txt
    可以看到ren的第二个参数不需要指定[drive:][path],即驱动和目录路径,而move的两个参数都要求使用完整的文件目录路径。当然move也可以在同一个文件夹目录下对文件名进行修改,只要参数设置对就行了。

运行过程和结果

运行脚本:E:\迅雷下载>start namecleaner.bat 电影天堂www.dy2018.com
运行结果:

这里写图片描述

终于没有广告了,舒服了。


参考

https://www.cnblogs.com/iTlijun/p/6137027.html
https://www.jb51.net/article/110243.htm
http://blog.sina.com.cn/s/blog_70371d7d0101dwb4.html
https://blog.csdn.net/albertsh/article/details/52788106
https://blog.csdn.net/i_likechard/article/details/65631403
https://www.jb51.net/article/18973.htm

猜你喜欢

转载自blog.csdn.net/weixin_30239361/article/details/81703851
今日推荐