我们如何使用批处理脚本将所有应用程序从 android(adb) 复制到 PC?
How can we copy all the apps from android(adb) to PC using Batch scripting?
myapps.txt - 包含通过 adb shell pm list packages > myapps.txt
找到的所有包的列表
package:com.flipkart.android
package:com.android.certinstaller
package:com.android.carrierconfig
package:com.reddit.frontpage
package:com.wapi.wapicertmanage
package:com.brave.browser
以下是我在批处理脚本中编写的代码,用于使用 ADB 将所有应用程序从 android 一次性复制到 PC。
其次,我用冒号 (:) 分割我的字符串,例如 -
string1 包含 package
和
string2 包含 com.google.android.youtube
@echo off
setlocal enabledelayedexpansion
for /f "tokens=1* delims=:" %%i in (myapps.txt) do (
echo j: %%j
set string2=%%j
adb shell pm path !string2! > tmp.txt
set /p new=< tmp.txt
@echo on
@echo new: !new!
@echo off
set "str=%new%"
set "string1=%str::=" & set "string3=%"
del tmp.txt REM delete file after reading from it.
REM creating new folder for each app
mkdir apps_%input%\%string2%
REM pulling app from Android to PC
adb pull %string3% apps_%input%\%string2%
set /a count+=1
echo Done !count!
)
这是执行 2 次 for
循环后的以下输出
j: com.flipkart.android
new: package:/data/app/com.flipkart.android-XOmoiAws7zOd07eM1nZIlg==/base.apk
A subdirectory or file apps_2\ already exists.
adb: error: failed to stat remote object 'apps_2\': No such file or directory
Done 1
j: com.android.certinstaller
new: package:/system/app/CertInstaller/CertInstaller.apk
A subdirectory or file apps_2\ already exists.
adb: error: failed to stat remote object 'apps_2\': No such file or directory
Done 2
请帮我看看为什么我会得到这个输出。另外apps_2
执行前不存在怎么提示已经存在
但是,同样的事情在 cmd 提示符下运行得很好:
mkdir apps_2\com.flipkart.android
adb pull /data/app/com.flipkart.android-XOmoiAws7zOd07eM1nZIlg==/base.apk apps_2\com.flipkart.android
这是我执行后收到的输出
/data/app/com.flipkart.android-XOmoiAws7zOd07eM1nZIlg==/base.apk: 1 file pulled. 33.8 MB/s (12691794 bytes in 0.358s)
批处理文件未按预期工作,因为 delayed expansion 仅用于 FOR 命令块中的部分而非所有环境变量引用。只有环境变量 input
可以在命令块内用 %input%
引用,因为它是唯一在命令块外定义且未在命令块内修改的环境变量。所有其他环境变量在命令块内 defined/modified 并在命令块内引用。因此,除了 input
之外的所有环境变量都必须使用 !
而不是 %
.
来引用
但是,此任务根本不需要使用环境变量。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
if not defined input set "input=1"
set "count=0"
if exist myapps.txt for /F "tokens=2 delims=:" %%I in (myapps.txt) do (
echo Getting path of app "%%I" ...
for /F "tokens=2 delims=:" %%J in ('adb.exe shell pm path "%%I" 2^>nul') do (
echo Path of app %%I is: "%%J"
rem Creating new folder for each app.
mkdir "apps_%input%\%%I" 2>nul
if exist "apps_%input%\%%I\" (
rem Pulling app from Android to PC.
echo Pulling app "%%I" to "apps_%input%\%%I" ...
adb.exe pull "%%J" "apps_%input%\%%I"
set /A count+=1
) else echo ERROR: Failed to create directory: "apps_%input%\%%I\"
)
)
if %count% == 1 (set "PluralS=") else set "PluralS=s"
echo Pulled %count% app%PluralS% from Android to PC.
endlocal
外层的FOR从myapps.txt
一行一行读取。由于选项 delims=:
,每一行都使用冒号作为分隔符拆分为子字符串。第一个冒号分隔的子字符串始终是 package
,这与此任务无关。因此,选项 tokens=2
用于将第二个子字符串 com.flipkart.android
分配给指定的区分大小写的循环变量 I
.
内部 FOR 循环在后台启动另一个命令进程,其中 %ComSpec% /c
和括号中的命令行作为附加参数附加。 adb
处理后台命令进程STDOUT的输出由FOR捕获并在启动后逐行处理cmd.exe
在 adb
终止后自行关闭。
adb
输出的单行再次使用冒号作为分隔符拆分为子字符串,并再次将第二个子字符串分配给指定的循环变量 J
.
接下来创建一个子目录,将应用程序名称作为目录名称,并将错误消息输出重定向到已存在的目录或无法创建的目录,从句柄 STDERR 到设备 NUL 抑制它。
然后对刚刚创建的目录进行存在性检查以验证它是否真的存在,如果存在,应用程序将从 Android 设备拉到 PC。
运行 cmd /?
in a command prompt window 的帮助输出在最后一页解释了包含 [= 的文件名(或任何其他参数字符串) 112=] 或这些字符 &()[]{}^=;!'+,`~
必须用双引号引起来。因此,所有引用当前分配给循环变量 I
(应用程序名称)和 J
(应用程序路径)的值的参数字符串都包含在 "
.
中
可以删除所有 echo
命令行和最后一个 if
条件,因为它们仅用于在执行批处理文件期间获取一些进度信息。
为了了解使用的命令及其工作原理,请打开 command prompt window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
echo /?
endlocal /?
for /?
if /?
mkdir /?
rem /?
set /?
setlocal /?
阅读有关 Using command redirection operators 的 Microsoft 文章,了解 2>nul
的解释。重定向运算符 >
必须在 FOR 命令行上使用脱字符 ^
进行转义,以便在 Windows 命令解释器处理此命令时将其解释为文字字符执行命令 FOR 之前的行,它在后台启动的单独命令进程中执行嵌入式 adb
命令行。
myapps.txt - 包含通过 adb shell pm list packages > myapps.txt
package:com.flipkart.android
package:com.android.certinstaller
package:com.android.carrierconfig
package:com.reddit.frontpage
package:com.wapi.wapicertmanage
package:com.brave.browser
以下是我在批处理脚本中编写的代码,用于使用 ADB 将所有应用程序从 android 一次性复制到 PC。 其次,我用冒号 (:) 分割我的字符串,例如 -
string1 包含 package
和
string2 包含 com.google.android.youtube
@echo off
setlocal enabledelayedexpansion
for /f "tokens=1* delims=:" %%i in (myapps.txt) do (
echo j: %%j
set string2=%%j
adb shell pm path !string2! > tmp.txt
set /p new=< tmp.txt
@echo on
@echo new: !new!
@echo off
set "str=%new%"
set "string1=%str::=" & set "string3=%"
del tmp.txt REM delete file after reading from it.
REM creating new folder for each app
mkdir apps_%input%\%string2%
REM pulling app from Android to PC
adb pull %string3% apps_%input%\%string2%
set /a count+=1
echo Done !count!
)
这是执行 2 次 for
循环后的以下输出
j: com.flipkart.android
new: package:/data/app/com.flipkart.android-XOmoiAws7zOd07eM1nZIlg==/base.apk
A subdirectory or file apps_2\ already exists.
adb: error: failed to stat remote object 'apps_2\': No such file or directory
Done 1
j: com.android.certinstaller
new: package:/system/app/CertInstaller/CertInstaller.apk
A subdirectory or file apps_2\ already exists.
adb: error: failed to stat remote object 'apps_2\': No such file or directory
Done 2
请帮我看看为什么我会得到这个输出。另外apps_2
执行前不存在怎么提示已经存在
但是,同样的事情在 cmd 提示符下运行得很好:
mkdir apps_2\com.flipkart.android
adb pull /data/app/com.flipkart.android-XOmoiAws7zOd07eM1nZIlg==/base.apk apps_2\com.flipkart.android
这是我执行后收到的输出
/data/app/com.flipkart.android-XOmoiAws7zOd07eM1nZIlg==/base.apk: 1 file pulled. 33.8 MB/s (12691794 bytes in 0.358s)
批处理文件未按预期工作,因为 delayed expansion 仅用于 FOR 命令块中的部分而非所有环境变量引用。只有环境变量 input
可以在命令块内用 %input%
引用,因为它是唯一在命令块外定义且未在命令块内修改的环境变量。所有其他环境变量在命令块内 defined/modified 并在命令块内引用。因此,除了 input
之外的所有环境变量都必须使用 !
而不是 %
.
但是,此任务根本不需要使用环境变量。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
if not defined input set "input=1"
set "count=0"
if exist myapps.txt for /F "tokens=2 delims=:" %%I in (myapps.txt) do (
echo Getting path of app "%%I" ...
for /F "tokens=2 delims=:" %%J in ('adb.exe shell pm path "%%I" 2^>nul') do (
echo Path of app %%I is: "%%J"
rem Creating new folder for each app.
mkdir "apps_%input%\%%I" 2>nul
if exist "apps_%input%\%%I\" (
rem Pulling app from Android to PC.
echo Pulling app "%%I" to "apps_%input%\%%I" ...
adb.exe pull "%%J" "apps_%input%\%%I"
set /A count+=1
) else echo ERROR: Failed to create directory: "apps_%input%\%%I\"
)
)
if %count% == 1 (set "PluralS=") else set "PluralS=s"
echo Pulled %count% app%PluralS% from Android to PC.
endlocal
外层的FOR从myapps.txt
一行一行读取。由于选项 delims=:
,每一行都使用冒号作为分隔符拆分为子字符串。第一个冒号分隔的子字符串始终是 package
,这与此任务无关。因此,选项 tokens=2
用于将第二个子字符串 com.flipkart.android
分配给指定的区分大小写的循环变量 I
.
内部 FOR 循环在后台启动另一个命令进程,其中 %ComSpec% /c
和括号中的命令行作为附加参数附加。 adb
处理后台命令进程STDOUT的输出由FOR捕获并在启动后逐行处理cmd.exe
在 adb
终止后自行关闭。
adb
输出的单行再次使用冒号作为分隔符拆分为子字符串,并再次将第二个子字符串分配给指定的循环变量 J
.
接下来创建一个子目录,将应用程序名称作为目录名称,并将错误消息输出重定向到已存在的目录或无法创建的目录,从句柄 STDERR 到设备 NUL 抑制它。
然后对刚刚创建的目录进行存在性检查以验证它是否真的存在,如果存在,应用程序将从 Android 设备拉到 PC。
运行 cmd /?
in a command prompt window 的帮助输出在最后一页解释了包含 [= 的文件名(或任何其他参数字符串) 112=] 或这些字符 &()[]{}^=;!'+,`~
必须用双引号引起来。因此,所有引用当前分配给循环变量 I
(应用程序名称)和 J
(应用程序路径)的值的参数字符串都包含在 "
.
可以删除所有 echo
命令行和最后一个 if
条件,因为它们仅用于在执行批处理文件期间获取一些进度信息。
为了了解使用的命令及其工作原理,请打开 command prompt window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
echo /?
endlocal /?
for /?
if /?
mkdir /?
rem /?
set /?
setlocal /?
阅读有关 Using command redirection operators 的 Microsoft 文章,了解 2>nul
的解释。重定向运算符 >
必须在 FOR 命令行上使用脱字符 ^
进行转义,以便在 Windows 命令解释器处理此命令时将其解释为文字字符执行命令 FOR 之前的行,它在后台启动的单独命令进程中执行嵌入式 adb
命令行。