windows/macOS for Batch Script批处理脚本基础运用
前言
为了更好的帮助我们理解,我们先来了解几个知识,1、什么是批处理脚本?
批处理脚本(Batch Script)是一种用于在操作系统中自动执行一系列命令的脚本文件。这种脚本通常用于简化重复性任务,通过编写一次性的脚本,用户可以自动化地执行多个命令或程序,而无需手动逐一输入。批处理脚本的功能非常强大,应用场景非常广泛。语法简单,易于学习和编写。批处理脚本作为一种强大的自动化工具,能够帮助我们更高效率地完成一些繁琐、重复的工作。只要我们善于运用它,就能够在工作和生活中享受到它带来的便利和乐趣。
2、在Windows和macOS上有什么区别。
批处理脚本在不同的操作系统中有不同的实现。在 Windows 系统中,批处理脚本通常以 .bat 或 .cmd 结尾,并使用批处理命令(如 cmd 命令)来执行。在 Unix 系统(如 Linux 和 macOS)中他是利用 shell(如 Bash、Zsh、Ksh 等)解释执行一系列命令。两个系统的的语法和命令有一些不同。
如下,一个简单的 Windows 批处理脚本是这样的:这个脚本使用了 Windows 特有的批处理命令,如 @echo off、echo、dir 和 pause,
@echo off
echo Hello, World!
dir
pause
一:创建一个简单的批处理脚本
1、在mac电脑上创建批处理脚本。
第一步:在启动台中使用文本编辑器,创建一个新的文本。
第二步:在左上角菜单栏,格式中,选择制作纯文本。
第三步:复制以下内容到文本框内:这一步需要注意的是,确保第一行是 #!/bin/bash 或 #!/bin/sh ,用于指定脚本的解释器。
#!/bin/bashecho "Hello, World!"
第四步:保存文件;确保文件后缀名为.sh,例如:hello.sh ; 保存的文本格式选择:西文(ASCII),如果下拉值中没有,需要自定义编码列表中去添加。
第六步:在终端中,进入脚本所在文件夹。通过以下命令,去执行脚本。执行效果如下:可以看到,已经成功输出了:"Hello, World!";说明我们的批处理脚本,编写运行成功。
a1234@Zh Documents % pwd /Users/a1234/Documents #需要先进入脚本所在文件夹 a1234@Zh Documents % chmod +x hello.sh # 确保脚本有执行权限 a1234@Zh Documents % ./hello.sh #运行脚本的命令 Hello, World! #最终输出
2、在Windows电脑上创建批处理脚本。
第一步:最好是用notpad++来写,在notpad++中输入以下内容:
@echo off echo Hello, World! pause
第二步:工具栏中编码选择:转为ANSI编码,并保存,后缀名需要是.bat 或者.cmd,保存到桌面
第三步:在桌面直接双击执行,上一步的.bat文件。以下是执行效果
到这儿,我们已经初步接触批处理文件。接下来就要开始正式的使用批处理文件,来执行一些业务了。
二:正式写一个批处理脚本,通过adb命令对安卓设备进行应用操作
在调试之前,建议开发者设置里边,先开启2个小功能,1、打开"指针位置" 2、打开USB调试且允许仅充电模式调试、前者,开启后,就可以看到手指点按屏幕的xy轴坐标位置,有助于我们定位屏幕坐标。后者是有助于调试的便捷。
1、咱们先直接把完整(.bat)脚本贴出来,然后再逐步骤去解析,这样也方便,有相关代码功底的小伙伴直接取用。macOS电脑shell脚本放在末尾。
@echo off :: 查询设备状态 for /f "delims=" %%i in ('adb get-state') do set DEVICE_STATE=%%i :: 判断设备状态 if "%DEVICE_STATE%"=="unknown" ( echo. echo. echo 请连接设备后,再重新执行本程序 echo. echo. pause exit /b 1 ) else ( echo. echo. echo 设备已就绪,请勿手动操作屏幕... ) :: 解锁密码的坐标,若密码是不同的数字,则在下面添加不同的点击语句,这里注释即可。 set X_COORD=1290 set Y_COORD=1447 setlocal :: 获取屏幕显示状态 for /f "tokens=2 delims==" %%i in ('adb shell dumpsys window policy ^| findstr "screenState="') do set "screenState=%%~i" :: 去除状态值两边的空格 set "screenState=%screenState: =%" :: 判断屏幕状态并执行操作 if /i "%screenState%"=="SCREEN_STATE_OFF" ( ::screenState=SCREEN_STATE_OFF,设备为息屏状态,直接点亮屏幕解锁即可 echo. echo. echo 正在唤醒设备... adb shell input keyevent KEYCODE_POWER timeout /t 2 /nobreak >nul echo. echo. ::打开解锁界面... adb shell input swipe 700 700 100 100 500 timeout /t 2 /nobreak >nul ::解锁设备... for /L %%i in (1,1,6) do ( adb shell input tap %X_COORD% %Y_COORD% ) timeout /t 2 /nobreak >nul ) else if /i "%screenState%"=="SCREEN_STATE_ON" ( ::screenState=SCREEN_STATE_ON,设备为亮屏状态,需要判断设备是否上锁 echo. echo. :: 获取设备锁定状态 for /f "tokens=2 delims==" %%i in ('adb shell dumpsys window policy ^| findstr "showing="') do ( set "showing=%%~i" :: 立即处理变量,避免后续可能的覆盖 setlocal enabledelayedexpansion if /i "!showing: =!"=="true" ( ::showing=true,设备为锁屏状态,直接解锁即可,若为false,已解锁,可以直接开始执行业务代码 echo. echo. ::打开解锁界面 adb shell input swipe 700 700 100 100 500 timeout /t 2 /nobreak >nul echo. ::解锁设备... for /L %%j in (1,1,6) do ( adb shell input tap %X_COORD% %Y_COORD% ) timeout /t 2 /nobreak >nul ) endlocal ) ) endlocal echo. echo. echo 启动应用... :: 杀掉应用 adb shell am force-stop com.xxx.xxx :: 等待设备响应(固定等待2秒) timeout /t 2 /nobreak >nul :: 使用monkey启动应用主界面 adb shell monkey -p com.xxx.xxx -c android.intent.category.LAUNCHER 1 >nul :: 等待设备响应(固定等待2秒) timeout /t 2 /nobreak >nul :: 点击要的功能按钮 adb shell input tap 2139 1242 :: 画一个正方形 adb shell input swipe 1089 1160 1089 930 500 adb shell input swipe 1089 930 1466 930 500 adb shell input swipe 1467 930 1466 1160 500 adb shell input swipe 1466 1160 1091 1160 500 :: 等待设备响应(固定等待2秒) timeout /t 2 /nobreak >nul setlocal set "DESKTOP_PATH=%USERPROFILE%\Desktop\test_photo" :: 获取当前时间戳 for /f "delims=" %%i in ('powershell -command "[System.DateTime]::Now.ToString(\"yyyyMMdd_HHmmss\")"') do set TIMESTAMP=%%i :: 在设备上截图,使用临时文件名 adb shell screencap -p /sdcard/Pictures/Screenshots/temp_AICreate.jpg :: 重命名截图文件,包含时间戳 adb shell "mv /sdcard/Pictures/Screenshots/temp_AICreate.jpg /sdcard/Pictures/Screenshots/AICreate_%TIMESTAMP%.jpg" :: 检查目标文件夹是否存在,如果不存在则创建 set "TARGET_FOLDER=%DESKTOP_PATH%" if not exist "%TARGET_FOLDER%" ( mkdir "%TARGET_FOLDER%" ) :: 保存截图文件,到电脑 adb pull /sdcard/Pictures/Screenshots/AICreate_%TIMESTAMP%.jpg "%TARGET_FOLDER%\AICreate_%TIMESTAMP%.jpg" >nul 2>nul :: 在设备上删除截图文件 adb shell "rm /sdcard/Pictures/Screenshots/AICreate_%TIMESTAMP%.jpg" :: 清理环境变量 endlocal :: 开始AI生图 echo. echo. echo AI生图中... adb shell input tap 1300 1152 :: 等待设备响应(固定等待30秒) timeout /t 30 /nobreak >nul echo. echo. echo 正在保存结果... :: 点击保存按钮 adb shell input tap 1540 1350 :: 等待设备响应(固定等待2秒) timeout /t 2 /nobreak >nul :: 休眠设备(电源键) echo 正在使设备进入休眠状态... adb shell input keyevent KEYCODE_SLEEP :: 批处理文件执行完毕 echo. echo. echo 所有操作已完成!正在为您打印设备信息... echo. echo. :: 输出设备以及应用信息 setlocal enabledelayedexpansion :: 定义变量来存储命令输出 set "brand=" set "model=" set "screen_resolution=" set "android_version=" set "app_version=" set "current_time=" :: 执行命令并捕获输出 for /f "delims=" %%i in ('adb shell getprop ro.config.marketing_name') do set "brand=%%i" for /f "delims=" %%i in ('adb shell getprop ro.product.model') do set "model=%%i" for /f "tokens=2 delims=:" %%i in ('adb shell wm size ^| findstr "Physical size"') do set "screen_resolution=%%i" for /f "delims=" %%i in ('adb shell getprop ro.build.version.release') do set "android_version=%%i" for /f "tokens=2 delims== " %%i in ('adb shell dumpsys package com.XXX.XXX ^| findstr "versionName"') do set "app_version=%%i" for /f "delims=" %%i in ('powershell "Get-Date -Format 'yyyy-MM-dd HH:mm:ss'" ') do set "current_time=%%i" :: 拼接品牌和型号 set "device_name=!brand! !model!" :: 输出结果 echo 设备型号:!device_name! echo 安卓版本:!android_version! echo 屏分辨率:!screen_resolution! echo 应用版本:!app_version! echo 当前时间:!current_time! echo. echo. endlocal pause
2、现在我们将以上代码,按照大致的功能模块,分为6个部分。来逐段、逐句解析代码。
第一部份:
先看看开头第一句是怎么写的。
@echo off :: 在批处理脚本的开头使用@echo off 命令,是用于关闭命令的回显功能。这意味着,在执行该命令之后的脚本内容时,命令本身不会在打印输出,只有命令的结果会被输出显示。 :: echo 是一个用于在命令行界面显示信息的命令。 :: off 是 echo 命令的一个参数,用于关闭回显。 :: @ 符号用于确保即使全局回显被打开(例如,在脚本的开头没有使用 @echo off),该行的命令也不会被显示。
第二部份:
接下来这段批处理脚本,先通过adb命令:adb get-state来查询设备连接状态,如果查出来的结果是unknown,就代表没有连接设备,这时候输出一句:请连接设备后,再重新执行本程序。用来提醒用户需要先链接设备。且通过 exit /b 1这段命令,终结脚本的执行,exit /b 1 在批处理脚本中的意义是:不关闭命令提示符窗口,立即退出当前批处理脚本或命令行块的执行语句,就是说下面的命令都不再去执行啦。如果不是unknown,那么就说明已经链接上设备,就不需要做任何操作。直接输出了一句:“设备已就绪,请勿手动操作屏幕...”,然后继续执行后续代码。
for /if "delims=" %%i in ('adb get-state') do set DEVICE_STATE=%%i :: for /f "delims=" %%i in ('adb get-state') do set DEVICE_STATE=%%i 是一个 for 循环,用于执行 adb get-state 命令并捕获其输出。 :: "delims=" 指定分隔符为空,这意味着整行输出都会被捕获为一个单独的变量值。 :: %%i 是循环变量,用于存储每一行的内容(在这个场景中,由于 adb get-state 只输出一行,所以 %%i 将包含整行输出)。 :: 'adb get-state' 是被执行的命令,用于查询ADB连接的设备状态。 :: do set DEVICE_STATE=%%i 表示将循环变量的值(即 adb get-state 的输出)赋值给环境变量 DEVICE_STATE。 :: 判断设备状态 :: 是批处理脚本中的注释符号,REM 也是注释符号。 if "%DEVICE_STATE%"=="unknown" ( :: if "%DEVICE_STATE%"=="unknown" 是一个条件判断语句,用于检查环境变量 DEVICE_STATE 的值是否等于 "unknown"。 :: 如果等于 "unknown",则执行 if 括号内的命令。如果不等于 "unknown",则执行 else 括号内的命令。 echo. echo. echo 请连接设备后,再重新执行本程序 echo. echo. :: echo. 用于输出一个空行,增加可读性。 :: pause 命令用于暂停脚本执行,并显示“Press any key to continue...”消息,等待用户按下任意键。 pause exit /b 1 ) else ( echo. echo. echo 设备已就绪,请勿手动操作屏幕... )
第三部份:
这段批处理脚本主要用于通过ADB命令控制Android设备,包括唤醒设备、判断屏幕状态、以及解锁设备。
这个实现逻辑,比上面的判断是否链接设备,要多一个子嵌套。我们来看看。
首先,adb shell dumpsys window policy ^| findstr "screenState="这个命令查是查询设备是否点亮屏幕的。查出来会有两个结果。
如果,screenState=SCREEN_STATE_OFF,则说明设备为息屏状态,直接点亮屏幕解锁即可。(即,第一个if语句里边的,就是解锁的命令)
如果,screenState=SCREEN_STATE_ON,则说明设备为亮屏状态,那就需要判断,设备是否上锁,(即,第二个else if语句里边的,就是查设备是否上锁的命令以及后续操作)
然后,adb shell dumpsys window policy ^| findstr "showing=" 这个命令查就是查询设备是否上锁的。查出来同样会有两个结果。
如果,showing=true,则说明设备为屏幕点亮的且是锁屏状态,这个时候直接解锁即可。
如果,showing不是true,则说明设备为屏幕点亮的且是解锁屏状态,那就不需要执行多余的步骤,可以直接开始接下来的业务操作了。
set X_COORD=1290 set Y_COORD=1447 ::这两行设置了解锁密码在屏幕上的X和Y坐标。我这儿是定位到了解锁键盘的0,因为我的设备密码是6个0。后续我通过adb命令,循环点击这个坐标6次,即可实现解锁,所以如果你的设备密码是不同的数字,那么这里就不适用,需要在下面的点击密码语句中,每个数字写一句。 setlocal ::setlocal这行开启了批处理脚本的本地环境变量作用域,意味着之后定义的变量在脚本结束时会自动销毁,不会影响到全局环境。文末的endlocal,这行结束了本地环境变量作用域,与脚本开始时的setlocal相对应。 :: 获取屏幕显示状态 for /f "tokens=2 delims==" %%i in ('adb shell dumpsys window policy ^| findstr "screenState="') do set "screenState=%%~i" :: 去除状态值两边的空格 set "screenState=%screenState: =%" :: 判断屏幕状态并执行操作 if /i "%screenState%"=="SCREEN_STATE_OFF" ( ::screenState=SCREEN_STATE_OFF,设备为息屏状态,直接点亮屏幕解锁即可 echo. echo. echo 正在唤醒设备... adb shell input keyevent KEYCODE_POWER ::用adb命令点击电源按键,点亮设备屏幕 ::input:这是Android shell中的一个命令,用于向设备发送输入事件,如按键、触摸等。 ::keyevent:这是input命令的一个参数,表示要发送的是一个按键事件。 ::KEYCODE_POWER:这是keyevent命令的一个参数,表示要模拟的按键是电源键。 timeout /t 2 /nobreak >nul ::timeout /t 2 /nobreak >nul 这条CMD命令的作用是:创建一个2秒的等待延迟,期间忽略任何中断尝试,并且不显示任何输出: ::timeout:这是Windows命令行中用于创建暂停或延迟执行的命令。它允许你指定一个时间段,在此期间命令行将不做任何事情,然后继续执行后续的命令。 ::/t 2:这个参数指定了延迟的时间长度。在这个例子中,/t 后面跟着的数字 2 表示延迟时间为2秒。 ::/nobreak:这个参数指示 timeout 命令忽略任何中断延迟的尝试。通常,你可以通过按键(如Ctrl+C)来中断 timeout 命令的执行,但使用 /nobreak 参数后,这种中断将被忽略,延迟将完整地执行。 ::>nul:这部分是输出重定向。在Windows命令行中,> 用于将命令的输出重定向到指定的文件或设备。nul 是一个特殊的设备,它接收任何发送到它的数据,但并不做任何处理(即,它是一个黑洞,吞噬所有数据)。因此,>nul 的作用是将 timeout 命令的任何输出(如倒计时信息)都重定向到 nul,从而不在命令行窗口中显示这些输出。 echo. echo. ::打开解锁界面... adb shell input swipe 700 700 100 100 500 ::这条ADB命令 adb shell input swipe 700 700 100 100 500 用于在Android设备上模拟一个滑动操作: ::input:这是shell环境中用于发送输入事件到Android设备的命令。它可以模拟按键、触摸等用户输入。 ::swipe:这是input命令的一个子命令,用于模拟一个滑动(拖拽)操作。 ::700 700:这两个数字指定了滑动操作的起始坐标(X轴和Y轴)。在这个例子中,滑动将从屏幕上的点(700, 700)开始。 ::100 100:这两个数字指定了结束坐标(X轴和Y轴) ::500:这个数字通常指定了滑动操作的持续时间(以毫秒为单位)。在这个例子中,滑动操作将在500毫秒内完成。 timeout /t 2 /nobreak >nul ::解锁设备... for /L %%i in (1,1,6) do ( adb shell input tap %X_COORD% %Y_COORD% ::前面有定义X_COORD和Y_COORD的值,这里的命令代表,循环点击6次目标的坐标,模拟点击6次锁屏密码。 ) ::这条命令结合了for循环和adb shell input tap命令来在Android设备上模拟重复点击操作。不过,需要注意的是,adb shell input tap命令每次循环都使用了相同的坐标(%X_COORD% 和 %Y_COORD%),因此它实际上只是在同一个位置重复点击。所以如果你的锁屏密码是不同的数字,需要把循环体删除,直接单独写adb的点击命令: :: ::for /L %%i in (1,1,6) do(:这是一个for循环的开始,用于在Windows批处理脚本中重复执行一系列命令。/L表示这是一个计数循环。循环变量%%i将从1开始,每次循环增加1,直到达到6(包含6)。因此,这个循环将执行6次。 ::adb shell input tap %X_COORD% %Y_COORD%:这个ADB命令,用于在Android设备的屏幕上模拟一个点击操作。 timeout /t 2 /nobreak >nul ) else if /i "%screenState%"=="SCREEN_STATE_ON" ( ::screenState=SCREEN_STATE_ON,设备为亮屏状态,需要判断设备是否上锁 echo. echo. :: 获取设备锁定状态 for /f "tokens=2 delims==" %%i in ('adb shell dumpsys window policy ^| findstr "showing="') do ( set "showing=%%~i" :: 立即处理变量,避免后续可能的覆盖 setlocal enabledelayedexpansion if /i "!showing: =!"=="true" ( ::showing=true,设备为锁屏状态,直接解锁即可,若为false,已解锁,可以直接开始执行业务代码 echo. echo. ::打开解锁界面 adb shell input swipe 700 700 100 100 500 timeout /t 2 /nobreak >nul echo. ::解锁设备... for /L %%j in (1,1,6) do ( adb shell input tap %X_COORD% %Y_COORD% ) timeout /t 2 /nobreak >nul ) endlocal ) ) endlocal
第四部份:
此前的代码,主要是为了解锁设备,设备准备好,现在我们要开始执行业务操作了,如下的一段代码中,重要的知识点,有2个:
1、使用adb命令,杀应用。
2、使用monkey打开应用的首页。
3、除此以外在应用程序的操作中,以下代码中仅使用了input tap点击命令,和input swipe滑动屏幕命令。还有更多种操作方式和场景等待你的发掘。
echo. echo. echo 启动应用... :: 杀掉应用 adb shell am force-stop com.xxx.xxx ::这条ADB命令,用于强制停止Android设备上的一个应用程序。我先杀掉目标程序,然后再后面重新启用: ::am:这是Activity Manager的缩写,是Android系统中的一个服务,负责管理应用程序的活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)等内容。通过am命令,可以启动活动、发送广播、强制停止应用程序等。 ::force-stop:这是am命令的一个子命令,用于强制停止指定的应用程序。与普通的停止命令不同,force-stop会立即停止应用程序的所有活动和服务,而不考虑应用程序是否正在处理重要的任务。 ::com.xxx.xxx:这是要被强制停止的应用程序的包名。可以通过查看包名的命令去获取并替换为自己应用的包名。查看包名命令:adb shell pm list packages。 :: 等待设备响应(固定等待2秒) timeout /t 2 /nobreak >nul :: 使用monkey启动应用主界面 adb shell monkey -p com.xxx.xxx -c android.intent.category.LAUNCHER 1 >nul ::monkey:这是Android SDK中的一个工具,用于生成伪随机的用户输入事件。用于向系统发送伪随机的用户输入事件流(如点击、触摸、手势和系统事件),模拟用户操作设备的行为。 ::-p com.xxx.xxx:-p 指定了monkey命令要发送事件的目标应用程序的包名。 ::-c android.intent.category.LAUNCHER: 这个是启动应用的首页。 ::1:这个数字通常表示要发送的事件数量。它表示只发送一个事件。 ::>nul:这个部分是将命令的输出重定向到nul,即无需输出结果。 :: 等待设备响应(固定等待2秒) timeout /t 2 /nobreak >nul :: 点击要的功能按钮 adb shell input tap 2139 1242 :: 画一个正方形 adb shell input swipe 1089 1160 1089 930 500 adb shell input swipe 1089 930 1466 930 500 adb shell input swipe 1467 930 1466 1160 500 adb shell input swipe 1466 1160 1091 1160 500 :: 等待设备响应(固定等待2秒) timeout /t 2 /nobreak >nul
第五部份:
接下来是一段,对设备的截图,并保存截图到本地电脑上的命令。其中的知识点有几个需要注意的:
1、%USERPROFILE% 这个变量会生成文件夹路径的用户路径,如:C:\Users\Hanmeimei
2、时间戳的定义和调用方式
3、if not exist (XXX)mkdir 判断目标,不存在即新建。
4、screencap截图命令
5、rm删除文件命令
6、mv重命名或移动文件的命令,
7、pull,下载的命令。
@echo off setlocal set "DESKTOP_PATH=%USERPROFILE%\Desktop\test_photo" :: 定义桌面文件夹路径, :: 使用 %USERPROFILE% 来替换 C:\Users\Hanmeimei,从而构建一个更加通用的文件路径。 :: \Desktop\test_photo 这个是桌面的文件夹路径。最终的文件夹名字,根据自己需要的去修改。 :: 把整个文件夹的路径,赋值给变量DESKTOP_PATH :: 获取当前时间戳 for /f "delims=" %%i in ('powershell -command "[System.DateTime]::Now.ToString(\"yyyyMMdd_HHmmss\")"') do set TIMESTAMP=%%i :: 这段命令是用于生成当前日期和时间的字符串,并将其赋值给一个名为 TIMESTAMP 的环境变量,后续部分可以直接使用这个变量来引用当前的日期和时间了: :: for /f:这是 for 命令的一种形式,用于对文件内容或命令的输出进行迭代处理。在这里,它用于处理 PowerShell 命令的输出。 :: "delims=":这个选项指定了分隔符。由于这里设置为空字符串,实际上意味着不使用任何分隔符。 :: %%i:在批处理脚本中,%%i 是循环变量。 :: in ('powershell -command "[System.DateTime]::Now.ToString(\"yyyyMMdd_HHmmss\")"'):这部分是 for 命令要迭代的命令。它执行一个 PowerShell 命令,该命令使用 .NET Framework 的 System.DateTime 类来获取当前日期和时间,并将其格式化为 yyyyMMdd_HHmmss 格式的字符串。 :: do set TIMESTAMP=%%i:这将 PowerShell 命令的输出(即当前日期和时间的字符串)赋值给 TIMESTAMP 环境变量。 :: 在设备上截图,使用临时文件名 adb shell screencap -p /sdcard/Pictures/Screenshots/temp_AICreate.jpg ::这段命令是用于在 Android 设备上通过 ADB工具截取屏幕截图,并将截图保存到设备的指定位置。: ::screencap:这是 Android 设备上的一个命令,用于捕获当前屏幕的截图。这个命令是 Android 系统的一部分,通常位于设备的 /system/bin 目录下。 ::-p:这是 screencap 命令的一个选项,表示以 PNG 格式保存截图。使用-p参数时,screencap命令会确保截图以PNG格式保存。PNG是一种无损压缩的位图图像格式,能够保留图像中的透明度和色彩深度,非常适合用于保存屏幕截图。 :: 重命名截图文件,包含时间戳 adb shell "mv /sdcard/Pictures/Screenshots/temp_AICreate.jpg /sdcard/Pictures/Screenshots/AICreate_%TIMESTAMP%.jpg" ::mv:这是 Unix/Linux 系统中的一个命令,这条adb命令使用了mv(move)命令,用于移动或重命名文件或目录,这里实际上是重命名为一个带有时间戳的文件名。 ::/sdcard/Pictures/Screenshots/temp_AICreate.jpg:这是要重命名的原始文件的路径和文件名。 ::/sdcard/Pictures/Screenshots/AICreate_%TIMESTAMP%.jpg:这是重命名后的文件的路径和文件名。这里的 %TIMESTAMP% ,上文中将这个变量定义为了一个时间戳。所以最终生成的文件名是这样的:AICreate_20241223_094030.jpg :: 检查目标文件夹是否存在,如果不存在则创建 set "TARGET_FOLDER=%DESKTOP_PATH%" if not exist "%TARGET_FOLDER%" ( mkdir "%TARGET_FOLDER%" ) :: "TARGET_FOLDER=%DESKTOP_PATH%",这里的“DESKTOP_PATH”的值在本段代码开头定义为:C:\Users\Hanmeimei\Desktop\test_photo :: 所以,if not exist "%TARGET_FOLDER%" (mkdir "%TARGET_FOLDER%")这段的意思是,如果不存在test_photo这个文件夹,则通过mkdir创建一个。 :: 保存截图文件,到电脑 adb pull /sdcard/Pictures/Screenshots/AICreate_%TIMESTAMP%.jpg "%TARGET_FOLDER%\AICreate_%TIMESTAMP%.jpg" >nul 2>nul ::adb pull:这是 adb 工具的一个命令,用于从 Android 设备上复制文件或目录到本地计算机。 ::>nul 2>nul:这部分是 Windows 命令提示符(cmd)的语法,用于处理命令的输出和错误信息。>nul 将标准输出重定向到 nul,这基本上意味着丢弃所有正常输出。2>nul 将标准错误输出也重定向到 nul,这意味着所有错误信息也会被丢弃。简单说就是任何信息都不要输出。大家有时间可以去尝试一下分别把两个取消后是什么样子。 :: 在设备上删除截图文件 adb shell "rm /sdcard/Pictures/Screenshots/AICreate_%TIMESTAMP%.jpg" ::rm 命令是用于删除文件或目录的命令行工具。 "remove" 的缩写。这里是把截图文件从移动设备中删除,用以保持设备没有运行脚本后产生的垃圾文件。 :: 清理环境变量 endlocal echo Done! pause
第六部分:
最后一段,用来输出设备信息、应用信息等,需要什么信息都可以自己去添加。
:: 输出设备以及应用信息 setlocal enabledelayedexpansion :: 这行命令启用了延迟变量扩展。这意味着在执行循环或条件语句时,可以正确地使用变量。 :: 定义变量来存储命令输出 set "brand=" set "model=" set "screen_resolution=" set "android_version=" set "app_version=" set "current_time=" :: 这些行定义了几个变量,用于存储后面通过命令获取的设备信息、应用版本和当前时间。 :: 执行命令并捕获输出 for /f "delims=" %%i in ('adb shell getprop ro.config.marketing_name') do set "brand=%%i" :: 这行命令使用 adb 工具获取设备的品牌信息,并将其存储在变量 brand 中。 for /f "delims=" %%i in ('adb shell getprop ro.product.model') do set "model=%%i" :: 这行命令获取设备的型号信息,并存储在变量 model 中。 for /f "tokens=2 delims=:" %%i in ('adb shell wm size ^| findstr "Physical size"') do set "screen_resolution=%%i" :: 这行命令获取设备的屏幕分辨率信息。它首先执行 adb shell wm size 命令获取屏幕大小,然后通过 findstr 过滤出包含 "Physical size" 的行,并使用冒号(:)作为分隔符提取分辨率。 for /f "delims=" %%i in ('adb shell getprop ro.build.version.release') do set "android_version=%%i" :: 这行命令获取设备的安卓版本信息,并存储在变量 android_version 中。 for /f "tokens=2 delims== " %%i in ('adb shell dumpsys package com.immotors.cockpitbuddy ^| findstr "versionName"') do set "app_version=%%i" :: 这行命令获取指定应用(com.XXX.XXXX)的应用版本信息。它首先执行 adb shell dumpsys package 命令,然后通过 findstr 过滤出包含 "versionName" 的行,并使用等号(=)和空格作为分隔符提取应用版本。 for /f "delims=" %%i in ('powershell "Get-Date -Format 'yyyy-MM-dd HH:mm:ss'" ') do set "current_time=%%i" :: 这行命令使用 PowerShell 获取当前时间,并将其格式化为 yyyy-MM-dd HH:mm:ss,然后存储在变量 current_time 中。 :: 拼接品牌和型号 set "device_name=!brand! !model!" :: 这行命令将品牌和型号拼接成一个新的字符串,并存储在变量 device_name 中。 :: 输出结果 echo 设备型号:!device_name! echo 安卓版本:!android_version! echo 屏分辨率:!screen_resolution! echo 应用版本:!app_version! echo 当前时间:!current_time! :: 这些行输出之前存储的各个变量的值。 echo. echo. endlocal pause
三:批处理脚本的更多运用
通过以上代码的认识,想必大家对批处理脚本的认识更加深刻了吧。本质上,批处理脚本就是一系列命令的集合体,它像是一个智能的助手,能够按照我们预设的逻辑和流程,自动化地完成一系列复杂的操作。而当我们掌握了更多的cmd命令、adb命令、shell命令等强大工具时,我们就能够构建出更加复杂、更加智能的业务流程。接下来,我们再衍生一些批处理脚本的案例。
场景应用1:windows电脑微信多开
以下命令,超级简单,就3个知识点,(下一个案例写到了开机自动启,有需要可以看看):
①、start
命令用于启动一个单独的“窗口”来运行指定的程序或命令。这儿记住替换成自己电脑桌面的程序快捷方式“绝对路径”即可。除了微信其他软件实际上也是可以的。
另外,在macOS上应该是用: open /Applications/WeChat.app
②、由于Program Files这个文件夹有空格,避免识别特殊符号报错,所以在前面加了双引号,
③、上面有专门讲过for循环,咱们再来看一次:
in (1,1,2) 定义了循环的参数:
第一个数字 1 是起始值。
第二个数字 1 是步长,表示每次迭代时变量增加的值。
第三个数字 2 是结束值,循环将一直执行到变量等于这个值为止。
@echo off for /L %%i in (1,1,10) do ( start "" "C:\Program Files\Tencent\WeChat\WeChat.exe" ) exit
应用场景二:一个简易有效的自动清理电脑垃圾文件的小工具
以下命令整体来说,就是把几条删除命令整合到一起,分别删除不同类型的垃圾文件数据。罗列出来的命令,不涉及用户数据文件,可以放心使用。
①命令解析:
rd 用于删除目录,而 del 用于删除文件。
/f:强制删除只读文件。没有这个参数,系统不会删除只读文件,而是会提示错误。
/s:从指定目录及其所有子目录中删除指定文件。没有这个参数,del命令只会删除当前目录下的文件。
/q:安静模式,删除文件时不询问确认。
*.*:这是一个通配符,表示匹配所有文件。
%windir%:这是一个环境变量,代表Windows的安装目录。在大多数情况下,它指向C:\Windows,但这取决于Windows的安装位置。
%systemdrive%也是环境变量,指向的是一个根目录(如C:\)
%userprofile%:这是一个环境变量,它代表当前用户的个人文件夹的路径:类似于C:\Users\YourUsername的目录,其中YourUsername是用户的登录名。
②自启动:
我们想要每天自动清理,那么就需要把这个.bat文件,创建一个快捷方式,然后将快捷方式放到自动启管理里边,以后开机就可以自动来执行文件,其实上面的微信多开,也可以这样操作,这样每天电脑开机,都可以帮我自动取多开微信,接下来看下windows开机自启动怎么设置:
第一步:通过鼠标右键.bat文件,在菜单中创建快捷方式。
第二步:然后按住win+r,弹出运行窗口,在窗口内输入shell:startup,回车。这一步的操作是因为,我们电脑的启动文件夹通常位于 C:\Users\[用户名]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup 。所以这里输入 shell:startup 并按下 Enter 键,是用来来快速访问这个文件夹。所以大家也可以在自己的文件夹窗口上面的文件路径里边,直接贴上文件路径,也是可以进入启动文件夹的: %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup ;
第三步:将步骤一创建的快捷方式拖进启动文件夹就行了。
@echo off echo 正在清理系统临时文件,请稍候... del /f /s /q %systemdrive%*.tmp REM 删除系统驱动器上所有.tmp临时文件。 del /f /s /q %systemdrive%*._mp REM 删除临时文件。 del /f /s /q %systemdrive%*.log REM 删除系统驱动器上所有.log日志文件。 del /f /s /q %systemdrive%*.gid REM 应用程序生成的文件。 del /f /s /q %systemdrive%*.chk REM 磁盘检查过程中发现的文件碎片或丢失的文件片段。 del /f /s /q %systemdrive%*.old REM 删除旧版本的文件。 del /f /s /q %windir%*.bak REM 删除Windows目录中所有的.bak备份文件。 del /f /s /q %windir%\prefetch*.* REM 删除预读取文件,这些文件用于加速Windows启动和应用程序加载。 rd /s /q %windir%\temp & md %windir%\temp REM 删除Windows临时文件夹中的所有内容,并重新创建该文件夹。 del /f /q %userprofile%\recent*.* REM 删除最近访问的文档列表。 del /f /s /q "%userprofile%\Local Settings\Temporary Internet Files*.*" REM 删除Internet临时文件,这些文件包含浏览器缓存的内容。 del /f /s /q "%userprofile%\Local Settings\Temp*.*" REM 删除用户临时文件夹中的所有内容。 echo 清理完成!只删除了系统临时文件和Internet临时文件。 pause
应用场景三:一个文字小游戏
以下是我在网上看到的一款迷宫小游戏,经过改进,使它巧妙地根据用户的不同选择来执行相应的代码逻辑。在游戏中,我们广泛采用了“:”标签与goto
命令的完美结合,实现了在不同游戏场景间的灵活跳转。这种编程技巧不仅使游戏流程更加顺畅,还极大地增强了游戏的互动性和可玩性。
此外,通过这款小游戏,我们深入学习了set /p
命令的应用。这一命令能够轻松地收集用户的输入数据,为游戏增添了更多的自定义和个性化元素。掌握这一输入语句后,仿佛为我们打开了一扇全新的窗户,让我们看到了批处理脚本的无限可能,以后调用时 %%variable%% 按照这个格式填入set /p 后面设置的变量名即可。
想象一下,有了这一技能,我们可以将一些常用的cURL接口封装成便捷的.bat
文件。通过简单地输入参数,就能轻松实现接口的调用,无需再依赖postman或JMeter这样的专业工具。这不仅提高了我们的工作效率,还让我们在接口测试方面拥有了更多的自主权。
更进一步地,我们还可以利用批处理脚本的强大功能,通过命令批量查找或修改文本、文件等内容。这为我们处理大量数据提供了极大的便利,同时也激发了我们的创造力和想象力。小伙伴们,现在你们可以充分发挥自己的聪明才智,利用这一技能去探索更多未知的领域,创造出更多实用的工具和程序吧!
@echo off title 简单文本冒险游戏 ::这行代码设置命令行窗口的标题为“简单文本冒险游戏”。 :game_loop ::这是一个标签(label),在批处理脚本中用于标记一个位置,以便使用goto命令跳转到这个位置。 :::end_game ::echo 游戏结束。 ::set /p continue="如果需要继续尝试,请输入“Y”: " ::if /i "%continue%"=="Y" goto game_loop ::文末的这段命令,就是对应的,:game_loop标签开始的地方,:end_game标签结束的地方,中间可以看成整个循环体,如果用户在整个游戏结束以后,输入了"Y",则通过goto game_loop,再次循环一遍。 goto start :start echo 你身处一间黑暗的房间,你听到了一些声音。 echo 你想要做什么? echo. echo 1. 点亮房间 echo 2. 打开门 echo 3. 寻找窗户 :input_start set /p choice="请输入你的选择(1-3): " ::使用set /p命令提示用户输入,并将输入的值赋给变量choice。 if "%choice%"=="1" goto light_room if "%choice%"=="2" goto open_door if "%choice%"=="3" goto find_window ::这三句话,会根据用户的输入不同,通过goto跳转到不同的代码块去。 echo 输入有误,请重新输入:1或2或3。 goto input_start ::如果输入的不是123,那么就会提示用户重新输入正确的值,且跳转到这个模块的开始地方,重新开始这一代码模块。 :light_room echo 你在房间里点燃了一盏灯,房间变得明亮了起来。 echo 你看到墙上有一张地图,你认为这可能会帮助你脱离险境。 echo. echo 1. 研究地图 echo 2. 忽略地图 :input_light_room set /p choice="请输入你的选择(1-2): " if "%choice%"=="1" goto study_map if "%choice%"=="2" goto ignore_map echo 输入有误,请重新输入:1或2。 goto input_light_room :open_door echo 你打开了门,走出了这个房间,你发现你正在一个迷宫中。 echo. echo 1. 沿着左边走 echo 2. 沿着右边走 :input_open_door set /p choice="请输入你的选择(1-2): " if "%choice%"=="1" goto left_path if "%choice%"=="2" goto right_path echo 输入有误,请重新输入:1或2。 goto input_open_door :left_path echo 你走了很久,最终你到达了出口,你成功逃脱了迷宫。That's great! goto end_game :right_path echo 你在迷宫中迷失了方向,最终你被困在里面,无法逃脱。Game over! goto end_game :find_window echo 你在房间里寻找窗户,但是你发现所有的窗户都被封死了。Game over! echo. echo 1. 再次寻找 echo 2. 回到房间中央 :input_find_window set /p choice="请输入你的选择(1-2): " if "%choice%"=="1" goto find_window if "%choice%"=="2" goto start echo 输入有误,请重新输入:1或2。 goto input_find_window :study_map echo 你研究了地图,最终你找到了出口。That's great! goto end_game :ignore_map echo 你忽略了地图,最终你在迷宫中迷失了方向,无法逃脱。Game over! goto end_game :end_game echo. echo. echo. set /p continue="游戏结束。重玩请输入“Y”: " if /i "%continue%"=="Y" goto game_loop ::这里是游戏结束后,会让用户选择是否继续,并识别用户的输入是不是Y,然后重新开始游戏。 :end echo 谢谢你的游玩!
应用场景四:设置屏幕的旋转方向
本段,咱们来说一下如何调整安卓设备的屏幕方向,从上面的业务代码中,可以发现,我们大量运用坐标拾取,那么横屏和竖屏的按钮坐标肯定是不一样的,所以我们需要保持一个固定的屏幕方向,而且业务中,也肯定会有很多场景是需要各种屏幕方向的。本段代码主要分为两步,先检查当前是否开启屏幕自动旋转功能。然后再执行切换屏幕方向,这儿切换屏幕方向的命令,需要在禁止自动旋转时才能生效,所以我们需要先把设备确保关闭自动旋转。
@echo off setlocal ::本段代码是要将屏幕方向调整为横屏,方便后续的操作 ::先执行adb shell settings get system accelerometer_rotation,查看执行结果,如果为1=自动旋转,则执行adb shell settings put system accelerometer_rotation 0,(0=禁止旋转) ::然后,再执行adb shell settings get system user_rotation,查看执行结果,如果结果不为1=横屏,则执行adb shell settings put system user_rotation 1, adb shell settings get system accelerometer_rotation | findstr /r /c:"1$" >nul if %errorlevel% equ 0 ( ::正在禁止自动旋转 adb shell settings put system accelerometer_rotation 0 ) :: 检查并设置用户旋转设置 adb shell settings get system user_rotation | findstr /r /c:"1$" >nul if %errorlevel% neq 0 ( :: 当前不为横屏,正在设置为横屏 adb shell settings put system user_rotation 1 ) :: 恢复打开自动旋转 adb shell settings put system accelerometer_rotation 1 endlocal echo 操作完成。 pause
四:延伸内容
1、通过以上学习,不难发现,批处理脚本的基础语法是cmd命令,和shell命令。下面,我列一些常用的命令。
CMD命令大全:https://www.cnblogs.com/xiaodi888/p/18633228
Shell命令大全:https://www.cnblogs.com/xiaodi888/p/18635097
2、批处理脚本,在对移动段设备进行自动化操作时,需要用到大量的adb命令相关知识,我准备了一篇比较详细的adb命令,以供参考,不全的地方,小伙伴们也可以留言补充交流。
adb命令大全:https://www.cnblogs.com/xiaodi888/p/18158228
3、文章开头的一段Windows系统上的批处理脚本,我们现在来写一份效果一样,但是可以在macOS系统上执行的批处理脚本。有兴趣的小伙伴们可以将两份脚本对比一下,看看有什么不一样的地方。
#!/bin/bash # 查询设备状态 DEVICE_STATE=$(adb get-state) # 判断设备状态 if [ "$DEVICE_STATE" == "unknown" ]; then echo echo echo "请连接设备后,再重新执行本程序" echo echo read -p "按任意键继续..." exit 1 else echo echo echo "设备已就绪,请勿手动操作屏幕..." fi # 解锁密码的坐标,若密码是不同的数字,则在下面添加不同的点击语句,这里注释即可。 X_COORD=1290 Y_COORD=1447 # 获取屏幕显示状态 screenState=$(adb shell dumpsys window policy | grep "screenState=" | awk -F'=' '{print $2}' | xargs) # 判断屏幕状态并执行操作 if [ "$screenState" == "SCREEN_STATE_OFF" ]; then echo echo echo "正在唤醒设备..." adb shell input keyevent KEYCODE_POWER sleep 2 echo echo # 打开解锁界面... adb shell input swipe 700 700 100 100 500 sleep 2 # 解锁设备... for i in {1..6}; do adb shell input tap $X_COORD $Y_COORD done sleep 2 elif [ "$screenState" == "SCREEN_STATE_ON" ]; then echo echo # 获取设备锁定状态 showing=$(adb shell dumpsys window policy | grep "showing=" | awk -F'=' '{print $2}' | xargs) if [ "$showing" == "true" ]; then echo echo # 打开解锁界面 adb shell input swipe 700 700 100 100 500 sleep 2 echo # 解锁设备... for j in {1..6}; do adb shell input tap $X_COORD $Y_COORD done sleep 2 fi fi echo echo echo "启动应用..." # 杀掉应用 adb shell am force-stop com.XXX.XXX sleep 2 # 使用monkey启动应用主界面 adb shell monkey -p com.XXX.XXX 1 > /dev/null 2>&1 sleep 2 # 设置桌面路径 DESKTOP_PATH="$HOME/Desktop/test_photo" # 获取当前时间戳 TIMESTAMP=$(date +"%Y%m%d_%H%M%S") # 在设备上截图,使用临时文件名 adb shell screencap -p /sdcard/Pictures/Screenshots/temp_AICreate.jpg # 重命名截图文件,包含时间戳 adb shell "mv /sdcard/Pictures/Screenshots/temp_AICreate.jpg /sdcard/Pictures/Screenshots/AICreate_${TIMESTAMP}.jpg" # 检查目标文件夹是否存在,如果不存在则创建 TARGET_FOLDER="$DESKTOP_PATH" if [ ! -d "$TARGET_FOLDER" ]; then mkdir -p "$TARGET_FOLDER" fi # 保存截图文件到电脑 adb pull /sdcard/Pictures/Screenshots/AICreate_${TIMESTAMP}.jpg "$TARGET_FOLDER/AICreate_${TIMESTAMP}.jpg" 2>/dev/null >/dev/null # 在设备上删除截图文件 adb shell "rm /sdcard/Pictures/Screenshots/AICreate_${TIMESTAMP}.jpg" # 输出设备以及应用信息 BRAND=$(adb shell getprop ro.config.marketing_name) MODEL=$(adb shell getprop ro.product.model) SCREEN_RESOLUTION=$(adb shell wm size | grep "Physical size" | awk '{print $3}') ANDROID_VERSION=$(adb shell getprop ro.build.version.release) APP_VERSION=$(adb shell dumpsys package com.XXX.XXX | grep "versionName" | awk -F'=' '{print $2}' | xargs) CURRENT_TIME=$(date +"%Y-%m-%d %H:%M:%S") # 输出结果 echo "设备型号:$BRAND $MODEL" echo "安卓版本:$ANDROID_VERSION" echo "屏分辨率:$SCREEN_RESOLUTION" echo "应用版本:$APP_VERSION" echo "当前时间:$CURRENT_TIME" echo echo # 休眠设备(电源键),可以根据需要决定是否取消注释 # echo "正在使设备进入休眠状态..." # adb shell input keyevent KEYCODE_SLEEP echo echo echo "所有操作已完成!" read -p "按任意键退出..."
结语
亲爱的朋友:
希望本文中描述的问题以及解决方案,可以帮助到您。当然,我们深知,问题和挑战总是层出不穷,新的情况也在不断涌现。如果读者朋友您有更好的方案,或者在实际应用中发现了文中的不足之处,请不吝分享您的宝贵建议。诚挚地邀请每一位读者加入我们的行列,共同完善这份教程。
感谢您的阅读与支持!
Dear frends,
We hope that the questions and solutions presented in this article can be of assistance to you. Of course, we are fully aware that problems and challenges are always emerging in an endless stream, and new situations are constantly arising. If you, our readers, have better solutions or have discovered any deficiencies in this article through practical application, please do not hesitate to share your valuable suggestions with us. We sincerely invite every reader to join us in continuously improving this tutorial.
Thank you for your reading and support!
See you,Parting is for better meeting!