Bash脚本执行ADB命令后提前退出循环的问题求助
问题根源
这个问题是Bash脚本里非常典型的标准输入流抢占问题,很多和adb、ssh这类默认会读取标准输入的命令行工具配合循环读取文件时,都会碰到这个坑。
你的循环是通过done < $PurgeFile把目标文件的内容作为while read的标准输入(stdin),而adb命令默认会从stdin读取内容。当在循环里执行adb shell ...时,它会把原本要留给read -r CURRENT_LINE的剩余文件内容全部“吸走”,导致下一次read没有内容可读,循环直接提前终止——这和ADB命令执行成功还是失败完全无关,只要它触发了stdin读取就会出问题。
快速修复方案
给你两种简单可靠的解决办法,任选其一就能解决问题:
方案1:给ADB命令重定向标准输入
让adb不要读取循环的stdin,把它的输入重定向到/dev/null(空设备),这样就不会抢占循环的输入流了。把你脚本里的ADB命令行改成下面这样:
adb shell pm uninstall --user 0 $CURRENT_LINE < /dev/null || true
替换完成后再执行脚本,循环就能正常遍历完文件里的每一行,逐个处理所有包名了。
方案2:换一种文件读取方式
用cat命令读取文件内容,再通过管道传给while循环。这种方式下,循环的输入流和ADB的输入流是相互独立的,不会出现抢占冲突。修改你脚本的循环部分:
LINE=1 # 用cat管道替代直接重定向到done cat "$PurgeFile" | while read -r CURRENT_LINE do if [[ $CURRENT_LINE != "" ]] then echo "attempting to remove: $LINE: $CURRENT_LINE" adb shell pm uninstall --user 0 $CURRENT_LINE || true fi echo "Made it here" ((LINE++)) echo "Made it to outer loop" done
⚠️ 小提醒:这种管道方式有个小副作用——循环内部的变量(比如$LINE)在循环结束后不会保留它的最终值,但对你这个脚本的核心功能没有影响。
为什么注释ADB命令就正常?
当你把ADB命令注释掉后,循环内部没有其他命令会读取stdin,read -r CURRENT_LINE就能逐行读取文件内容,自然能完整遍历整个文件,所有调试输出也都正常。
验证效果
用方案1修改后,再执行脚本,就能看到脚本会逐个处理文件里的所有非空行,不管ADB卸载成功还是失败,循环都会一直跑直到文件末尾,完全符合你的预期。
内容来源于stack exchange

