Windows批处理脚本实现ADB文件批量传输:自动化与效率提升实战

Windows批处理脚本实现ADB文件批量传输:自动化与效率提升实战

1. 项目概述:为什么我们需要批处理来管理ADB文件传输?

如果你经常和安卓设备打交道,无论是作为开发者进行应用调试,还是作为极客玩家管理手机里的文件,adb pushadb pull这两个命令绝对是你的老朋友。手动敲命令,一次两次还行,但当你需要从几十个不同目录拉取日志,或者向设备推送一整套资源文件时,重复劳动不仅枯燥,还极易出错。文件名输错一个字母、路径少打一个斜杠,都可能让操作前功尽弃。

这时候,一个简单的 Windows 批处理(.bat)脚本就能成为你的效率倍增器。它能把一系列繁琐的adb命令自动化、批量化执行。我最初写这类脚本,就是因为被频繁的测试日志收集工作搞得不胜其烦。每次测试完,都需要手动从设备的/sdcard/Android/data/[包名]/files/log/这类深目录里,把十几个日志文件拉取到本地按日期分类的文件夹中。手动操作不仅慢,还经常漏文件。自从用批处理脚本自动化之后,整个过程从原来的几分钟压缩到十几秒,而且准确率100%。

这个项目要解决的,就是如何利用 Windows 系统的批处理脚本,来批量、可靠、可定制地执行adb push(推送文件到设备)和adb pull(从设备拉取文件到电脑)操作。它特别适合以下场景:安卓应用开发者需要批量部署测试资源或拉取调试日志;手机发烧友需要定期备份或同步特定文件夹;测试工程师需要自动化收集测试结果文件。接下来,我会从设计思路到具体实现,把其中的门道和踩过的坑都详细拆解一遍。

2. 脚本核心设计与思路拆解

写一个能用的批处理脚本不难,但写一个健壮、好用、能应对各种意外情况的脚本,就需要一些设计考量了。我们不能仅仅是把命令堆叠在一起,而是要思考整个流程的鲁棒性和用户体验。

2.1 核心需求与功能定义

首先,我们要明确这个批处理脚本需要具备哪些核心功能:

  1. 批量操作:能够处理一个文件列表或一个目录下的所有文件,而不是单个文件。
  2. 路径灵活性:允许用户方便地指定源路径(电脑或设备)和目标路径,最好能通过简单修改脚本开头的变量来实现。
  3. 状态反馈与日志:执行过程中,需要清晰地告诉用户当前在做什么,成功了还是失败了。最好能生成一个日志文件,记录所有操作和可能出现的错误,方便事后排查。
  4. 容错与交互:如果设备未连接、文件不存在等情况发生,脚本不能直接崩溃退出,而应该给出明确的提示,并可能提供重试或跳过的选项。
  5. 可扩展性:脚本结构应该清晰,方便后续添加新功能,比如在传输前后执行额外的adb shell命令(例如修改文件权限),或者根据日期动态创建目标文件夹。

基于这些需求,我设计的脚本通常会采用“配置区 + 函数模块 + 主流程”的结构。配置区定义路径、开关等参数;函数模块封装pushpull检查设备等独立功能;主流程则按顺序调用这些函数,并处理逻辑。

2.2 为什么选择批处理(.bat)而不是 PowerShell 或其他?

这是一个很实际的选择问题。PowerShell 功能无疑更强大,但对于adb命令操作这个特定场景,批处理有它的独特优势:

  • 兼容性极佳:从 Windows XP 到最新的 Windows 11,.bat 脚本无需任何额外环境或执行策略修改,双击即可运行。这对于需要在不同测试机、同事电脑上快速部署脚本的情况非常友好。
  • 与命令行环境无缝集成adb本身就是一个命令行工具,批处理调用它是最自然的方式,输出和错误流处理起来很直接。
  • 学习与修改成本低:批处理的语法相对简单,即使是不太熟悉脚本的测试人员或开发者,也能看懂并修改脚本中的几个路径变量。这使得脚本的共享和维护成本降低。

当然,如果你的操作非常复杂,涉及复杂的JSON/XML解析、网络请求等,那么PowerShell或Python是更好的选择。但对于纯粹的adb文件传输自动化,批处理是“够用且好用”的典范。

2.3 关键挑战与应对策略

在实现过程中,有几个挑战需要提前规划:

  • 设备连接状态管理:脚本执行的第一件事必须是检查是否有设备通过adb连接。没有设备,一切操作都无从谈起。
  • 文件路径中的空格与特殊字符:这是批处理脚本的经典“坑”。路径或文件名如果包含空格,必须用双引号包裹,否则会被拆分成多个参数。我们的脚本必须能妥善处理这类情况。
  • adb命令本身的错误adb push可能会因为设备存储空间不足、权限拒绝而失败;adb pull可能会因为文件不存在而失败。脚本需要捕获这些错误并作出合理反应,比如记录到日志并继续执行下一个文件,而不是整体中断。
  • 操作确认与防止误覆盖:在pull操作时,如果本地已存在同名文件,是直接覆盖,还是跳过,或是询问用户?这需要设计一个策略。

我的策略是:“先检查,后执行;勤记录,慎覆盖”。在核心操作前做好状态检查;所有操作和结果都输出到屏幕并写入日志;对于文件覆盖,默认采用“跳过已存在文件”的保守策略,并通过配置项允许用户修改为强制覆盖。

3. 脚本核心细节解析与实操要点

让我们深入脚本内部,看看几个关键部分是如何实现的,以及有哪些必须注意的细节。

3.1 设备连接检查:脚本稳健性的第一道防线

一个健壮的脚本必须在开始文件操作前确认设备在线。直接使用adb devices命令并解析其输出是最可靠的方法。

@echo off REM 检查ADB设备连接 echo [%date% %time%] 正在检查ADB设备连接... adb devices | findstr /R /C:"^[0-9a-f].*device$" >nul 2>nul if %errorlevel% equ 0 ( echo 设备已连接。 set DEVICE_STATUS=CONNECTED ) else ( echo 错误:未找到已连接的ADB设备。请确保: echo 1. 设备已开启USB调试模式。 echo 2. 电脑已安装正确的ADB驱动。 echo 3. 设备已通过USB线连接,或网络ADB已配置并连接。 echo 4. 在命令行中运行 `adb devices` 能看到设备。 pause exit /b 1 )

要点解析与避坑指南:

  1. adb devices的输出格式:一条正常的设备连接行类似于abcdef012345 device。我们使用findstr命令,通过正则表达式^[0-9a-f].*device$来匹配:以十六进制数字开头、中间任意字符、以“device”结尾的行。这能有效过滤掉头部的“List of devices attached”和尾部的空行,以及状态为offlineunauthorized的设备。
  2. 错误流重定向>nul 2>nul将命令的标准输出和错误输出都丢弃,不显示在屏幕上。我们只关心findstr的执行结果(即%errorlevel%)。这样界面更干净。
  3. 明确的错误提示:当检查失败时,不要只简单说“设备未连接”。应该给出可能的原因和排查步骤,如上方的四点提示。这能极大减少使用者的困惑。
  4. 设置状态变量:这里将DEVICE_STATUS设为CONNECTED,是为了后续可能的多设备选择逻辑预留扩展性。虽然当前脚本处理的是单设备,但良好的习惯是让脚本结构易于扩展。

3.2 处理文件路径:绕开空格的“陷阱”

在批处理中,参数以空格分隔。因此,任何包含空格的路径,如果不加引号,都会被拆散。例如,adb push C:\My Documents\file.txt /sdcard/会被解析为向adb传递三个参数:C:\MyDocuments\file.txt/sdcard/,这必然导致失败。

黄金法则:在脚本中,所有传递给外部命令(如adb)的路径变量,都用双引号包裹。

set LOCAL_FILE="C:\Users\YourName\Documents\My File.txt" set DEVICE_PATH="/sdcard/Download/" adb push %LOCAL_FILE% %DEVICE_PATH%

即使你确信当前路径没有空格,这也是一个必须养成的好习惯,能避免未来某天突然引入带空格路径时脚本崩溃。在定义路径变量时就直接加引号,或者在拼接路径时确保引号完整。

3.3 实现批量拉取(Pull):遍历与判断

批量pull的核心是“遍历”。我们需要一个源文件列表,然后循环处理每一个。这个列表可以硬编码在脚本里,也可以通过读取一个文本文件,或者直接遍历设备上的某个目录来动态生成。

方案一:遍历本地列表文件(推荐用于精确控制)创建一个filelist.txt,每行写一个设备上的文件路径。脚本读取并逐行拉取。

set FILE_LIST=filelist.txt set DEVICE_BASE="/sdcard/Android/data/com.example.app/files/" set LOCAL_BASE="D:\Backup\" for /f "usebackq delims=" %%f in ("%FILE_LIST%") do ( echo [%date% %time%] 正在拉取: %%f adb pull "%DEVICE_BASE%%%f" "%LOCAL_BASE%" if !errorlevel! neq 0 ( echo [警告] 拉取失败: %%f >> pull_log.txt ) else ( echo [成功] 已拉取: %%f >> pull_log.txt ) )

方案二:拉取整个目录如果你想拉取设备上某个文件夹下的所有内容(包括子目录),adb pull命令本身支持目录操作。

set DEVICE_DIR="/sdcard/DCIM/Camera/" set LOCAL_DIR="E:\PhoneBackup\Camera_%date:~0,4%%date:~5,2%%date:~8,2%\" echo 正在拉取整个目录: %DEVICE_DIR% adb pull "%DEVICE_DIR%" "%LOCAL_DIR%"

重要注意事项:

  • adb pull目录的行为:它会将设备上的整个目录结构(包括子文件夹)原样拉取到本地。如果本地目标文件夹不存在,adb会创建它。
  • 网络与性能:拉取大量小文件时,由于每个文件都需要建立一次ADB通信,速度可能会比拉取单个大文件慢很多,且对USB连接稳定性要求高。如果可能,先在设备上打包(如用tar),再拉取压缩包,最后在电脑上解压,效率会高得多。
  • 错误处理:上面的脚本片段中使用了if !errorlevel! neq 0来检查上一个命令(adb pull)的退出代码。在for循环内部,我们需要使用延迟变量扩展(!errorlevel!而不是%errorlevel%),并在脚本开头加上setlocal enabledelayedexpansion。这是批处理中处理循环内变量动态变化的关键技巧。

3.4 实现批量推送(Push):覆盖策略与权限管理

批量pushpull思路类似,但有一些独特的点。

覆盖策略adb push默认行为是覆盖目标位置已存在的文件,且没有提示。这有时是危险的。一个更安全的脚本可以在推送前,通过adb shell ls检查目标文件是否存在,并询问用户或根据配置决定是否跳过。

setlocal enabledelayedexpansion set LOCAL_SOURCE="C:\AppAssets\*" set DEVICE_TARGET="/sdcard/AppAssets/" for %%f in (%LOCAL_SOURCE%) do ( set filename=%%~nxf adb shell ls "%DEVICE_TARGET%!filename!" >nul 2>nul if !errorlevel! equ 0 ( echo 文件已存在,跳过: !filename! echo [跳过] !filename! >> push_log.txt ) else ( echo 正在推送: !filename! adb push "%%f" "%DEVICE_TARGET%" echo [推送] !filename! >> push_log.txt ) )

权限问题:推送到设备系统目录(如/system/app/)或某些数据目录可能需要root权限。通常的adb push可能失败。这时需要分两步:

  1. adb push到临时目录,如/data/local/tmp/
  2. 通过adb shellsu(如果有root)移动文件并设置正确权限。
adb push myapp.apk /data/local/tmp/ adb shell su -c "mv /data/local/tmp/myapp.apk /system/app/ && chmod 644 /system/app/myapp.apk"

注意:修改系统分区需要设备已解锁并获取 root 权限,且分区必须是可写的(例如通过adb remount)。对普通用户和应用数据目录,通常不需要这么复杂。

4. 完整脚本实操过程与核心环节实现

下面,我将结合一个功能相对完整的实战脚本,来演示如何将上述思路整合在一起。这个脚本实现了:检查设备、批量拉取指定文件列表、批量推送一个本地文件夹,并附带日志功能。

4.1 脚本准备与环境配置

在开始编写脚本前,请确保你的工作环境已就绪:

  1. ADB环境:确保adb命令可以在命令行中直接运行。将Android SDK的platform-tools目录(包含adb.exe)添加到系统的PATH环境变量中。验证方法:打开新的命令提示符(CMD),输入adb version,能看到版本信息即表示成功。
  2. 设备连接:用USB线连接安卓设备,并在设备上开启“开发者选项”中的“USB调试”模式。在电脑命令行运行adb devices,应能看到你的设备序列号,状态为device
  3. 脚本编辑器:使用任何文本编辑器,如 Notepad++、VS Code,甚至系统自带的记事本。关键是要以ANSIUTF-8 without BOM编码保存文件,否则中文字符可能显示为乱码。文件扩展名必须为.bat

4.2 完整脚本代码与逐段解析

创建一个新文件,命名为adb_file_manager.bat,将以下代码复制进去。我会在代码中以REM注释的形式进行详细解析。

@echo off REM adb_file_manager.bat - 批量ADB文件推送/拉取管理脚本 REM 作者:你的名字 REM 版本:1.0 REM 功能:检查设备,批量拉取文件列表,批量推送本地文件夹,记录完整日志。 setlocal enabledelayedexpansion REM 启用延迟环境变量扩展,这是在循环内部正确读取动态变量(如errorlevel)的关键。 REM ========== 用户配置区域 ========== REM 请根据你的实际情况修改以下变量 REM 1. 设备上待拉取的文件列表(每行一个完整路径) set FILELIST_TO_PULL=files_to_pull.txt REM 2. 设备上拉取文件的基准目录(与列表中的路径拼接) set DEVICE_BASE_PATH=/sdcard/ REM 3. 拉取文件到本地的存放目录 set LOCAL_PULL_DIR=D:\ADB_Backup\ REM 4. 本地待推送的文件夹路径 set LOCAL_PUSH_DIR=C:\MyAppAssets\ REM 5. 推送文件到设备的目标目录 set DEVICE_PUSH_DIR=/sdcard/Download/MyAppAssets/ REM 6. 日志文件路径 set LOG_FILE=adb_operation_%date:~0,4%%date:~5,2%%date:~8,2%.log REM 日志文件名包含日期,例如 adb_operation_20231027.log REM ========== 函数定义区域 ========== REM 函数:记录日志 REM 用法:call :log "日志信息" :log echo [%date% %time%] %~1 >> %LOG_FILE% goto :eof REM 函数:检查ADB设备连接 :check_device echo [%date% %time%] 正在检查ADB设备连接... adb devices | findstr /R /C:"^[0-9a-f].*device$" >nul 2>nul if !errorlevel! equ 0 ( echo 设备已连接。 call :log "ADB设备检查通过,设备已连接。" ) else ( echo 错误:未找到已连接的ADB设备。 echo 请检查:1. USB调试已开启 2. 驱动正常 3. 设备已授权 4. 连接线正常。 call :log "错误:ADB设备检查失败,未找到已连接设备。" pause exit /b 1 ) goto :eof REM 函数:批量拉取文件 :pull_files echo. echo [%date% %time%] 开始批量拉取文件... call :log "开始批量拉取文件操作。" if not exist "%FILELIST_TO_PULL%" ( echo 错误:拉取文件列表 '%FILELIST_TO_PULL%' 不存在。 call :log "错误:拉取文件列表不存在。" goto :eof ) if not exist "%LOCAL_PULL_DIR%" ( echo 创建本地目录:%LOCAL_PULL_DIR% mkdir "%LOCAL_PULL_DIR%" ) set /a SUCCESS_COUNT=0 set /a FAIL_COUNT=0 for /f "usebackq delims=" %%i in ("%FILELIST_TO_PULL%") do ( set "device_file=%%i" REM 去除可能的首尾空格 for /f "tokens=*" %%a in ("!device_file!") do set device_file=%%a if not "!device_file!"=="" ( echo 正在拉取:!device_file! adb pull "%DEVICE_BASE_PATH%!device_file!" "%LOCAL_PULL_DIR%" if !errorlevel! equ 0 ( echo [成功] set /a SUCCESS_COUNT+=1 call :log "拉取成功:!device_file!" ) else ( echo [失败] set /a FAIL_COUNT+=1 call :log "拉取失败:!device_file!" ) ) ) echo 拉取完成。成功:!SUCCESS_COUNT! 个, 失败:!FAIL_COUNT! 个。 call :log "批量拉取完成。成功:!SUCCESS_COUNT! 个, 失败:!FAIL_COUNT! 个。" goto :eof REM 函数:批量推送文件夹 :push_folder echo. echo [%date% %time%] 开始批量推送文件夹... call :log "开始批量推送文件夹操作。" if not exist "%LOCAL_PUSH_DIR%" ( echo 错误:本地推送目录 '%LOCAL_PUSH_DIR%' 不存在。 call :log "错误:本地推送目录不存在。" goto :eof ) echo 推送本地目录:%LOCAL_PUSH_DIR% echo 到设备目录:%DEVICE_PUSH_DIR% adb push "%LOCAL_PUSH_DIR%" "%DEVICE_PUSH_DIR%" if !errorlevel! equ 0 ( echo [推送操作完成] call :log "推送文件夹操作完成:%LOCAL_PUSH_DIR% -> %DEVICE_PUSH_DIR%" ) else ( echo [推送操作可能出错] call :log "警告:推送文件夹操作可能出错,返回码:!errorlevel!" ) goto :eof REM ========== 脚本主流程 ========== echo ======================================== echo ADB 批量文件管理脚本 echo ======================================== REM 步骤1:检查设备 call :check_device REM 步骤2:执行批量拉取 call :pull_files REM 步骤3:执行批量推送 call :push_folder REM 步骤4:结束 echo. echo [%date% %time%] 所有操作执行完毕。 echo 详细日志请查看:%LOG_FILE% call :log "所有脚本操作执行完毕。" pause

脚本使用步骤:

  1. 修改配置:用文本编辑器打开adb_file_manager.bat,根据注释修改“用户配置区域”的六个路径变量。
  2. 准备拉取列表:在与脚本相同的目录下,创建files_to_pull.txt文件。每行写入一个你想从设备拉取的文件或目录的相对路径(相对于DEVICE_BASE_PATH)。例如:
    DCIM/Camera/IMG_20231001.jpg Android/data/com.tencent.mm/MicroMsg/Download/ Download/my_document.pdf
  3. 准备推送文件夹:确保LOCAL_PUSH_DIR指向的本地文件夹存在,并且里面有你要推送的文件。
  4. 运行脚本:双击adb_file_manager.bat运行。脚本会依次执行设备检查、拉取列表文件、推送本地文件夹,并在屏幕上显示进度,同时在同目录下生成一个带日期的日志文件(如adb_operation_20231027.log)。

4.3 脚本关键环节深度剖析

  1. 延迟变量扩展(setlocal enabledelayedexpansion!var!:这是本脚本最重要的技术点之一。在for循环中,如果直接使用%errorlevel%%var%,它们会被在循环开始前一次性替换成当时的值,不会随循环更新。使用!errorlevel!!var!可以确保每次循环都读取变量的最新值。这是批处理编写复杂逻辑时必须掌握的技巧。

  2. 日志函数的实现(:log:我定义了一个简单的日志函数。它利用>>追加重定向将信息写入日志文件。%~1表示函数的第一个参数。goto :eof(End Of File)是批处理中结束函数执行的常用方法。通过call :log “信息”来调用,使得日志记录代码复用且清晰。

  3. 文件列表的读取与清洗(for /f “usebackq delims=”usebackq允许我们使用双引号来引用文件名(”filelist.txt”)。delims=将分隔符设置为空,意味着整行内容都会作为一个值被读取,即使行内有空格、逗号等也不会被切断。内部的for /f “tokens=*”循环用于去除每行首尾可能存在的空格,避免路径错误。

  4. 错误处理的层次:脚本进行了多层错误处理。首先是设备检查,失败则直接退出。其次是文件/目录存在性检查(如拉取列表文件、本地推送目录),不存在则给出错误并跳过该部分操作。最后是每个adb命令执行后的错误码检查(!errorlevel!),并分别计数成功与失败。这种结构保证了脚本在遇到部分错误时仍能继续执行其他任务,而不是整体崩溃。

5. 常见问题与排查技巧实录

即使脚本写得再严谨,在实际运行中还是会遇到各种问题。下面是我在长期使用中积累的一些典型问题及其解决方法。

5.1 问题:运行脚本时提示“adb不是内部或外部命令”

  • 现象:双击批处理文件,窗口一闪而过,或者显示错误信息“adb不是内部或外部命令,也不是可运行的程序或批处理文件。”
  • 原因:系统PATH环境变量中没有包含adb.exe所在的目录。
  • 解决方案
    1. 临时方案(仅对当前CMD窗口有效):在运行脚本前,先手动打开CMD,并切换到adb.exe所在的目录执行。或者,在脚本最开头添加一行,直接指定adb的完整路径:
      set ADB_PATH=C:\Android\Sdk\platform-tools\adb.exe REM 然后后面所有调用adb的地方,都用 "%ADB_PATH%" 代替 adb
    2. 永久方案(推荐):将Android SDK的platform-tools目录添加到系统环境变量PATH中。
      • 右键点击“此电脑” -> “属性” -> “高级系统设置” -> “环境变量”。
      • 在“系统变量”中找到并选中Path,点击“编辑”。
      • 点击“新建”,添加你的platform-tools目录路径,例如C:\Users\YourName\AppData\Local\Android\Sdk\platform-tools
      • 确定所有对话框。需要重新启动任何已打开的命令行窗口,新的PATH才会生效。

5.2 问题:设备检查通过,但adb pulladb push失败

  • 现象:脚本显示设备已连接,但执行文件传输时卡住或报错,例如error: closedfailed to copy, 或者权限错误。
  • 原因与排查
    1. USB连接不稳定:尝试拔插USB线,或更换一个USB端口(优先使用机箱后置的USB口)。关闭电脑和手机的屏幕保护、休眠设置。
    2. 设备锁屏或休眠:有些设备在锁屏状态下会限制ADB文件访问。确保设备屏幕已解锁,并进入开发者选项,将“USB调试(安全设置)”或“充电时不锁定屏幕”等选项打开。
    3. 文件权限不足:尝试拉取或推送系统受保护目录的文件。对于普通应用,只能访问/sdcard/(外部存储)和自身的数据目录。确认你操作的路径是否有权限。可以尝试先在adb shell下用ls -l命令查看文件权限。
    4. 设备存储空间不足:推送文件时,目标设备存储空间不够。使用adb shell df -h检查存储空间。
    5. 路径错误:这是最常见的原因。仔细检查配置的路径:
      • 设备路径是否以/开头?是否区分大小写?
      • 本地Windows路径是否使用了正确的反斜杠\?在批处理变量中,是否用双引号包裹了完整路径?
      • 对于拉取,列表文件中的路径是否相对于DEVICE_BASE_PATH正确?
    6. ADB服务异常:有时ADB服务会卡住。可以尝试在命令行中执行adb kill-server然后adb start-server重启ADB服务。

5.3 问题:脚本中的中文显示或处理乱码

  • 现象:脚本中echo的中文、日志文件中的中文,或者文件名中的中文,显示为乱码(如“锟斤拷”)。
  • 原因:批处理文件 (.bat) 的编码与Windows命令行(CMD)的代码页不匹配。CMD默认使用GBK(代码页936)编码,而许多现代编辑器默认保存为UTF-8。
  • 解决方案
    1. 保存脚本为ANSI编码:用Notepad++打开你的.bat文件,在菜单栏选择“编码” -> “转为ANSI编码”,然后保存。这是最一劳永逸的方法。
    2. 修改CMD活动代码页(临时):在脚本开头添加chcp 65001 >nul,可以切换到UTF-8代码页。但这可能带来其他兼容性问题,且需要终端字体支持UTF-8,不推荐作为主要方案。

5.4 问题:for循环只执行了一次,或者文件列表没读全

  • 现象:明明files_to_pull.txt中有多行,但脚本只处理了第一行就结束了。
  • 原因:文件列表中存在空行,或者某些行的格式导致for /f解析提前终止。另外,如果文件列表是Unix/Linux格式(行尾是LF),在Windows下也可能出现解析问题。
  • 解决方案
    1. 清理你的列表文件,删除所有不必要的空行。
    2. 确保脚本中for /f使用了delims=选项,这样不会因为行内的空格而截断。
    3. 尝试在for /f选项中添加eol=,将行注释字符设置为空,防止某些以分号;开头的行被忽略。
      for /f "usebackq eol= delims=" %%i in ("%FILELIST%") do (...)
    4. 使用Notepad++等工具,将文件列表的格式从“UTF-8”转换为“UTF-8无BOM”,或者从“Unix (LF)”转换为“Windows (CR LF)”。

5.5 高级技巧:使用变量动态构建带时间戳的备份目录

在拉取文件时,为了避免覆盖之前的备份,我们经常希望按日期时间创建子文件夹。批处理中可以通过字符串截取来获取日期时间。

REM 获取当前日期和时间,格式为 YYYYMMDD_HHMMSS set BACKUP_TIMESTAMP=%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%%time:~6,2% REM 替换时间中的空格(小时若为个位数,前面会有空格) set BACKUP_TIMESTAMP=%BACKUP_TIMESTAMP: =0% set LOCAL_PULL_DIR=D:\ADB_Backup\%BACKUP_TIMESTAMP%\

这样,每次运行脚本,拉取的文件都会自动存放到像D:\ADB_Backup\20231027_143025\这样的新目录中,实现了自动归档。

5.6 脚本优化:增加交互式菜单选择

对于更复杂的场景,你可以将脚本升级为带菜单的交互式版本,让用户选择执行拉取、推送还是其他操作。

@echo off :menu cls echo =============================== echo ADB 文件管理工具 echo =============================== echo 1. 批量拉取文件 echo 2. 批量推送文件夹 echo 3. 检查设备状态 echo 4. 重启ADB服务 echo 5. 退出 echo =============================== set /p choice=请选择操作 (1-5): if "%choice%"=="1" goto pull if "%choice%"=="2" goto push if "%choice%"=="3" goto check if "%choice%"=="4" goto restart if "%choice%"=="5" exit /b echo 选择无效,请重新输入。 pause goto menu :pull REM 调用之前定义的拉取函数或代码块 call :pull_files pause goto menu :push REM 调用之前定义的推送函数或代码块 call :push_folder pause goto menu :check adb devices pause goto menu :restart adb kill-server adb start-server echo ADB服务已重启。 pause goto menu

这个框架使得脚本更加用户友好,功能也更易于扩展。你可以把前面章节中封装好的函数:pull_files:push_folder直接整合进来。