Windows批处理文件(.bat和.cmd)

cmd文件和bat文件的区别

从文件描述中的区别是,cmd文件叫做:Windows命令脚本,bat文件叫:批处理文件,两者都可以使用任意一款文本编辑器进行创建、编辑和修改,只是在cmd中支持的命令要多于bat。

批处理文件是一种没有什么固定格式的文件,他可以处理一条或者多条命令,文件的扩展名是:.cmd或者.bat,文本里面的每一行就是一条处理指令,双击运行它的时候,Windows就会调用cmd.exe去运行它。

Windows批处理(cmd/bat)常用命令

指令描述

指令:echo和@

@echo off  通常我们将这条指令写在我们批处理文件的第一行,因为有了这条指令之后,当我们在运行.bat的时候,就不会将文件里面的内容打印出来了,如果没有这句话,会先去将文件里面的内容打印在屏幕上

echo off 这条指令之后的内容不会被打印,但是这个指令会被打印

@  某一条指令不想被打印,可以在前面加上@

echo. 或 echo:  换行,即回车

打印:echo

使用echo命令将设置的变量进行回显,即打印。

echo %a%
echo %wang%

赋值:set

注意等号左边不能有空格,等号右边的空格会被当做字符串的一部分

set a=1
set wang=wang

注释:REM 和 ::

REM 和 ::的区别:rem会被打印在屏幕上,::不会被打印在屏幕上

rem set a=1
::set b=2

标题:title

title 新标题名字_wang03

暂停:pause

当我们需要在文件运行的中间让其暂停一下

# 暂停,在控制台就会显示:“请按任意键以继续. . .”
pause

# 区别是不显示“请按任意键继续. . .”,nul相当于空文件,把这些文字隐去了。
pause > nul

# 自定义提示语
echo 其他提示语 & pause > nul

退出:exit

# 运行bat文件后让cmd窗口动关闭
exit

注意:如果使用exit就不要使用pause命令

启动:start

作用:启动一个单独的窗口以运行指定的程序或命令
当我们在cmd窗口输入:help start之后,然后回车,就会给我们弹出start命令的解析:

Windows批处理文件( called.bat或called.cmd )可以通过多种方式从另一批处理文件( caller.bat或caller.cmd )或交互式cmd.exe提示中caller.cmd :

    直接呼叫: called.bat
使用call命令: call called.bat
使用cmd 命令: cmd /c called.bat
使用启动命令: start called.bat

指令:call

如果你想在某一批处理程序中调用另外一个批处理文件,就是用call指令。

call temp.bat

延时:timeout

timeout  /?

跳转:goto

跳转到标签

@echo off
:start
cls
set /p numis=请输入数字1或2:
if /i "%numis%"=="1" goto 1
if /i "%numis%"=="2" (goto 2) else (echo 输入有误!&&pause>nul&&goto start)
:1
echo 你输入的是1
pause>nul&&goto start
:2
echo 你输入的是2
pause>nul&&goto start

循环:for

语法格式

FOR %variable IN (set) DO command [command-parameters]

参数说明

  • %variable 指定一个单一字母可替换的参数。 在bat脚本中使用%%变量;在cmd窗口中使用%变量。
  • (set) 指定一个或一组文件。可以使用通配符。
  • command 指定对每个文件执行的命令。
  • command-parameters 为特定命令指定参数或命令行开关。

注意:在批处理程序中使用 FOR 命令时,指定变量请使用 %%variable而不要用 %variable。变量名称是区分大小写的,所以 %i 不同于 %I。
for语句中in和do是必须有的;in之后,do之前,也就是set的括号不能省略;

一个简单的例子:

@echo off
for  %%i in (ITPro进化论) do echo %%i
pause

@echo off
ehco 显示当前目录下所有的文件名
for %%a in (*.*) do echo "%%a"
rem echo.是换行的意思
echo
echo 显示当前目录下以.md结尾的文件
for %%b in (*.md) do echo "%%b"
pause

实例:批量修改文件名

@echo off
setlocal enabledelayedexpansion

REM 设置要重命名的文件夹路径
set "folderPath=C:\Path\To\Your\Folder"

REM 设置要去除的前缀
set "prefix=OldPrefix_"

REM 遍历文件夹中的所有文件
for %%F in ("%folderPath%\%prefix%*") do (
  REM 获取文件的扩展名(包含.)
  set "extension=%%~xF"

  REM 获取文件名(去掉前缀)
  set "newName=%%~nF"
  set "newName=!newName:%prefix%=!"

  REM 组合新的文件名
  set "newName=!newName!!extension!"

  REM 输出重命名前后的文件名(可选)
  echo Renaming "%%~nxF" to "!newName!"

  REM 执行重命名操作
  ren "%%F" "!newName!"
)
echo Batch renaming completed.
pause

注意:含有空格的路径要加引号,所以如上代码尽量加引号

for扩展

for /F 解析文本,读取字符串

for /f ["options"] %variable in ('command') do command
其中,关键字"options"表示一些可选的参数,%variable用于定义一个用来存储命令输出值的变量,'command'表示要执行的命令。
options常用的参数选项包括:
-delims:指定分隔符,用于将命令输出的每行数据分割成多个部分。
-tokens:用于指定要存储的数据部分的位置。默认情况下,for/f命令会将整行数据存储到变量中。
-skip:跳过指定的行数。
-eol:指定行注释的字符。

示例:

# 按行读取该文件的内容,并逐行进行处理
for /f "tokens=*" %i in (c:\data.txt) do echo "%i"

# 读取该文件的内容,使用=号分割成两个部分,然后输出键和值
for /f "delims== tokens=1,2" %i in (c:\config.txt) do echo Key:%i, Value:%j

# 读取目录文件列表,并按时间排序,使用.分割文件名和扩展名,然后输出
for /f "tokens=1,2delims=." %i in ('dir /b/od *') do echo filename:%i, suffix:%j

# 当定义顿号“、”、减号“-”和点号“.”三个标点符号为分隔符后,原文被分隔成四个部分。
# 1、饶天亮-玫瑰爱人.wma
# 2、黄凯勤-伤感的恋人.mp3
for /f "tokens=1,2-4delims=、-." %i in (song.txt) do echo %i %j %k %l

讲解:
"delims=、-."表示定义顿号、减号和点号为分隔符。默认情况下,用做分隔符的标点符号将被忽略。
"tokens=1,3"表示只提取第一列和第三列。
"tokens=1,2-4"中的“2-4”表示第二至第四列。
"%i %j"对应于“token”后面的列数。有多少列就要有多少个输出变量,并且各变量中的字母存在先后顺序。

for /D 读文件夹,默认只读文件

FOR /D %variable IN (set) DO command [command-parameters]

实例:for语句加/D命令与不加/D命令的对比。

@echo off
echo 默认显示当前目录下的文件名
for %%a in (*) do echo "%%a"
rem echo.是换行的意思
echo.
echo 加上/D后显示当前目录下的文件夹名
for /D %%b in (*) do echo "%%b"
pause

实例:显示C盘下的目录,不包含子目录

@echo off
for /D %%i in (C:/*) do echo "%%i"
pause
for /R 指定目录

如果在 /R 后没有指定目录规范,则使用当前目录,包括子目录下的文件。

FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]

实例:在D盘搜索Notepad--.exe程序并打开。

@echo off
for /r D:/ %%i in (Notepad--.exe) do (
    if exist %%i (
        echo 找到了 Notepad--.exe
        REM 去启动 Notepad--.exe
        start %%i
        echo 软件已启动
        pause
        goto end
    )
)
echo 没有找到 Notepad--.exe
:end
for /L 以增量形式生成一个数字序列

FOR /L %variable IN (start,step,end) DO command [command-parameters]

实例:

@echo off
echo 创建1到6的序列
for /L %%i in (1,1,6) do echo %%i
echo.
echo 创建6到1的序列
for /L %%i in (6,-1,1) do echo %%i
echo.
echo 从2开始,每次增加3,到16结束的序列
for /l %%i in (2,2,13) do echo %%i
pause

实例:使用for语句创建100个txt文件

@echo off
cd test
for /l %%i in (1,1,100) do (
    cd>%%i.txt
)
echo 100个txt文件创建完成。
pause >nul
for循环中对变量循环赋值

“setlocal enabledelayedexpansion”表示开启变量延迟,可以监测for循环中变量的动态变化;
“set /a v+=1”对变量v每循环一次加1。

实例:批量修改文件名

:: 设置UTF-8编码
chcp 65001

@echo on
setlocal enabledelayedexpansion

cd D:/QMDownload/图片_生肖

rem 设置要替换的文本和新的文本
set replace=a100
set newtext=Q萌-
set suffix=jpg

set /a v =0;
for /L %%i in (1,1,12) do (
    set k=%%i
    if !k! lss 10 (
       set k=0!k!
    )
    set filename=%replace%!k!.%suffix%
    @echo 原文件名: !filename!
    set /a v+=1
    set new_filename=%newtext%-!v!.%suffix%
    @echo 新文件名:!new_filename!
    ren !filename! !new_filename!
)
rem echo.
@echo 批量修改文件名完成!
pause

for跳出循环方法:break 或 goto

for循环批量生成随机数
@echo off
chcp 65001
setlocal enabledelayedexpansion

set /a min=1
set /a max=100
:loop
set /a rd=%RANDOM% %% (max - min + 1) + min
rem timeout /t 1
ping 127.0.0.1 -n 2 > nul
REM 判断rd等于50就跳出循环
if !rd! equ 50 (
    echo 选中号码:!rd!,恭喜您喜提大奖 666!!!
) else (
    echo 选中号码:!rd!,非常遗憾没有抽中,继续摇号
    goto loop
)
pause
for循环批量生成UUID
@echo off
chcp 65001
setlocal enabledelayedexpansion

set min=1
set max=100
set /a mod=!max!-!min!+1
for /l %%i in (1,1,10) do (
    powershell -c "[guid]::NewGuid().ToString().ToUpper()"
    set k=%%i
    set /a rd=!random!%%!mod!+!min!
    echo !k!-!rd!
)
pause

if 条件表达式

指令格式为:if 条件表达式 (…)

注意
英文缩写的比较操作符,左右两边必须有空格;
“==”两侧可以不加空格,比较表达式和()之间必须有空格

@echo off
Set inputValue=15
if %inputValue%==15 (echo %inputValue%等于15)
if %inputValue% equ 15 (echo %inputValue%等于15)
pause

# 判断字符串是否相等的时候,参数"/I(i)"可以在比较字符串时串忽略大小写
if /i "abc"=="ABC" (echo 大小相等) else (echo 大小不等)

# else if换行时,上右括号")"后需跟 “^”
if %inputValue% gtr 100 (
    echo 大于100
)^
else if %inputValue% gtr 10 (
    echo 大于10
)^

在bat脚本中,if条件判断语句共有6种比较操作符,分别为

操作符(不区分大小写)描述全称
equ等于equal
neq不等于no equal
lss小于less than
leq小于等于leq less than or equal
gtr大于greater than
geq大于等于geq greater than or equal
其中,只有等于操作符可以使用符号 “==” 表示,其他操作符只能使用英文简写

当参与比较的字符串是字符串时,将被转换为对于的ASCII码进行比较

If条件语句拓展功能

If exist

判断驱动器、文件夹或文件是否存在

注意:if后的变量要加 %%

@echo off
set filepath=d:\data
if exist %filepath% (
    echo %filepath%存在
)
if not exist %filepath% (
    echo %filepath%不存在
)
pause
If defined

判断某个变量是否已经被赋值

注意:if后的变量 不能加 %%

@echo off
set /p filepath=请输入:
if defined filepath (
    echo filepath存在
)
if not defined filepath (
    echo filepath不存在
)
pause
if结合errorlevel使用

结果判断,说明:环境变量errorlevel的初始值为0,当一些命令执行不成功,就会返回一个数值,如:1 ,2 等

@echo off

rem call "D:\VS Code\Microsoft VS Code\Code.exe"

call  C:\Users\Administrator\Desktop\printf.bat

if %errorlevel%  == 0 (
    echo 前条执行成功
) else (
    echo 前条执行失败
)
pause

bat中文乱码

点击菜单【文件】-【另存为】操作,选择ANSI编码进行保存。
image

chcp申明字符编码
image

代码页 映射的字符集
936 GB2312
20127 US-ASCII
65001 UTF-8

脚本启动和关闭项目

启动脚本:start.bat

@echo off
%1 mshta vbscript:CreateObject("WScript.Shell").Run("%~s0 ::",0,FALSE)(window.close)&&exit
java -jar cn-admin.jar --spring.profiles.active=dev >> startup.log 2>&1 &
exit

关闭脚本:stop.bat

@echo off
set port=8081
REM 查杀进程
for /f "tokens=1-5" %%i in ('netstat -ano^|findstr ":%port%"') do (
     echo kill the process %%m who use the port
     taskkill /pid %%m -t -f
     goto q
)
:q
::延时3秒
timeout /t 3
::删除日志文件
del /f /s /q  startup.log

Java代码执行CMD方式

方式一:

Runtime runtime = Runtime.getRuntime();
runtime.exec("cmd /c test.bat")

方式二:

ProcessBuilder pro = new ProcessBuilder("cmd","/c","test.bat");
pro.start();

Java执行bat文件注意事项

Java代码执行bat文件可以使用绝对路径,如:start E://root/work/test.bat

但使用java代码运行bat文件其中再执行其它文件,需要先cd到指定目录,再运行目录下的文件,如:

@echo off
E:
cd E://root/work
java -jar app.jar -Dfile.encoding=utf-8 >> startup.log 2>&1 &
exit

Java根据titile查杀pid进程

public class Test{
    // title 指启动脚本中设置的title
    public void close(String title) throws Exception{
        Runtime rt = Runtime.getRuntime();
        // 根据字符搜索进程列表
        String cmd = "cmd/c tasklist /v | findstr /c:\"" + title "\"";
        Process pro = rt.exec(cmd);
        BufferedReader br = new BufferedReader(new InputStreamReader(pro.getInputStream()));
        String line = null;
        while((line = br.readLine())!=null){
            // 判断此进程是否包含 title 信息
            if(line.contains(title)){
                List<String> list = new ArrayList();
                String[] arr = line.split(" ");
                for(int i=0;i<arr.length;i++){
                    if(StringUtils.isNotEmpty(arr[i])){
                        list.add(arr[i].trim());
                    }
                }
                String pid = list.get(1); // 第2个信息就是pid
                cmd = "cmd /c taskkill /f /fi \"pid eq " + pid + "\" /t";
                rt.exec(cmd);
            }
        }
    }
}

Jar/Nginx/Redis注册成服务

Jar注册服务示例

1、下载winsw
https://github.com/winsw/winsw/releases
image

2、配置XML文件
修改xml文件名与winsw.exe程序名保持一致,即:test_admin.exe和test_admin.xml

<service>
  <id>testService</id>
  <name>Test后台服务</name>
  <description>Test后台服务接口</description>
  <!-- java环境变量 -->
  <env name="JAVA_HOME" value="%JAVA_HOME%"/>
  <executable>java</executable>
  <arguments>-jar admin.jar --spring.profiles.active=prod</arguments>
  <!-- 开机启动 -->
  <startmode>Automatic</startmode>
  <!-- 日志配置 -->
  <logpath>D:\workspace\FWG0006\InstallPackge\behind\logs</logpath>
  <logmode>rotate</logmode>
</service>

3、启动服务

test_admin.exe install       # 安装服务
net start testService        # 启动服务,testService指xml中的service.name

4、卸载服务

net stop testService         # 停止服务,testService指xml中的service.name
test_admin.exe uninstall     # 卸载服务

Nginx注册服务示例

nginx_sevice.xml

<service>
 <id>nginx</id>
 <name>Nginx 服务</name>
 <description>Nginx本地服务</description>
 <executable>nginx.exe</executable>
 <stopexecutable>nginx.exe -s stop</stopexecutable>
 <depend></depend>
 <!-- 开机启动 -->
 <startmode>Automatic</startmode>
 <!-- 日志配置 -->
 <logpath>logs_service</logpath>
 <log mode='roll-by-time'>
    <pattern>yyyyMMdd</pattern>
 </log>
</service>

其它参考Jar注册服务示例

Redis注册服务示例

不用参考上面,根据实际需要把以下命令组装成bat脚本

# 注册服务
redis-server.exe --service-install redis.windows-service.conf
# 启动服务
redis-server --service-start
# 停止服务
redis-server --service-stop
# 卸载服务
redis-server --service-uninstall
posted @ 2022-10-19 10:27  空还是空  阅读(704)  评论(0编辑  收藏  举报