虽然说bat批处理脚本就是连续执行一条条DOS命令,相对于C语言等编程语言来说显得十分有限,但对多个文件进行批量操作是非常方便的。这篇文章旨在记录一下我无意中想到的使用bat的一个小实例。
对批处理和DOS命令熟悉的大神可以直接跳过。
本人喜欢看电影,习惯了将电影在各大资源网站上面下载下来有空看看。下载下来的视频文件就会遇到下面这样的情况:
强迫症患者简直不能忍。。
但是文件夹里面有几百个视频文件,逐个逐个改对于程序员来说是不可接受的。
之前也尝试过使用python码一个脚本遍历文件然后去掉相关的广告字眼,但是毫无疑问这种情况批处理脚本更适合。
直接上代码:
@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=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
但是这里要注意的是冒号需要慎用,冒号后面紧跟一个以字母数字开头的字符串,我们称之为有效标号,是可以被call
和goto
语句识别的;而冒号后面紧跟一个非字母数字的特殊符号就成为无效标号,可以起到注释作用。
重定向符
重定向符号是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=
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 11段 12段 13段 14段 15段 16段 >>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
运行显示结果:
11段 13段 14段 15段 16段
21段 23段 24段,25段,26段
31段 33段 34段-35段-36段
请按任意键继续. . .
setlocal enabledelayedexpansion
来开启变量延迟,并且后续对需要延迟赋值的变量使用一对感叹号!!括起来。 sum
、传入子程序的old_string
和new_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结尾。
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