Ich möchte eine Reihe von Apps auf einem Android-Gerät löschen, die alle mit demselben Paket beginnen. Ich erhalte diese mit folgendem Befehl:
$ adb shell ls /data/data | grep -i com.company
com.company.android.app.adwidget
com.company.android.app.attendancereports
com.company.android.app.atteventmanagement
com.company.android.app.buttonwidget
com.company.android.app.clockwidget
Jetzt möchte ich adb uninstall
für jeden dieser Paketnamen Folgendes ausführen xargs
: Ich dachte daran, Folgendes zu verwenden :
$ adb shell ls /data/data | grep -i com.company | xargs -n1 echo adb uninstall
adb uninstall com.company.android.app.adwidget
adb uninstall com.company.android.app.attendancereports
adb uninstall com.company.android.app.atteventmanagement
adb uninstall com.company.android.app.buttonwidget
adb uninstall com.company.android.app.clockwidget
Es sieht so aus, als würde es funktionieren, also entferne ich echo
:
$ adb shell ls /data/data | grep -i com.company | xargs -n1 adb uninstall
Failure
Failure
Failure
Failure
Failure
Wenn Sie jedoch jeden Befehl unabhängig ausführen, erhalten Sie Success
:
$ adb uninstall com.company.android.app.adwidget
Success
Was mache ich falsch?
grep
, verwenden Sie einfach einen Globus:adb ls /data/data/*com.company* | xargs -n1 adb uninstall
sollten Sie das Gleiche tun. Funktioniert es, wenn Sie es tunfor i in adb ls /data/data/*com.company*; do adb uninstall "$i"; done
?adb shell ls
, nichtadb ls
, macht das einen Unterschied machen?/data/data/something
statt seinsomething
.no matches found
. Das Zitieren verhält sich genauso wie in meiner Frage (Failure
für alle Hinrichtungen)Antworten:
Obwohl das Problem letztendlich durch CR-Zeichen in der
adb shell
Ausgabe verursacht wurde (eingefügt durch die tty-Zeilendisziplin des auf dem Ziel-Android-System erstellten pty (siehe hier für weitere Details)), eine andere mögliche Erklärung (und ich werde es dort belassen Für zukünftige Leser, da dies ein häufiges Problem ist,xargs
könnte dies das gewesen sein in:Abhängig von der
xargs
Implementierung istadb
stdin entweder/dev/null
oder die Pipe vongrep
. In jedem Fall wird es nicht das tty sein, und das kann der Grund sein, warum esadb
fehlschlägt, wenn es erwartet, mit dem Benutzer interagieren zu können.Mit GNU
xargs
und einer Shell mit Unterstützung für die Prozessersetzung (wiezsh
) können Sie Folgendes ändern:In diesem Fall wird
xargs
die Liste aus der als Argument angegebenen Datei gelesen, mit der-a
Sie stdin in Ruhe lassen können.Oder da Sie erwähnen
zsh
, könnten Sie verwenden:(Verwenden von
-L
anstelle von-n
aszargs
's-n
begrenzt die Gesamtzahl der Argumente aufadb
(einschließlich desuninstall
einen), was bedeutet, dass wir benötigen würden-n 2
).Oder verwenden Sie einfach eine Schleife, die in diesem Fall noch kürzer und besser lesbar wäre:
quelle
xargs
undfor
-Befehle geben den gleichen Fehler wie meine xargs-Version aus:Failure
für alle Ausführungen.zargs
Befehl gibt mirzargs: argument list too long
(dankezargs
übrigens)for
Schleife ein(set -x; foo loop here)
und sehen Sie, wo sich dasadb
von Hand unterscheidet. Möglicherweise enthält die Ausgabe einige nachgestellte Wagenrücklaufzeichen (aka$'\C-M'
).+zsh:48> x=com.company.android.app.attendancereports +zsh:48> adb uninstall com.company.android.app.attendancereports Failure
. Ich sehe keine seltsamen Charaktere.adb uninstall com.company.android.app.attendancereports
funktioniert? Möglicherweise müssen Sie eine Verzögerung zwischen denadb
Befehlen einfügen ?$'\C-M'
oben gezeigte. Geheimnis gelüftet.adb shell ls /data/data | grep -i com.company
Als ich die Ausgabe in eine Datei umleitete und sie mit einem Hexeditor untersuchte, stellte ich fest, dass sie an einen Wagenrücklauf im Windows-Stil\r\n
(0x0D 0x0A) angehängt sind . Also von der Loswerden\r
mittr -d '\r'
dem Problem gelöst.Ganzer Befehl mit
for
(aus der Antwort von Stéphane Chazelas ):Oder ähnlich mit
xargs
:Eine andere Option (wie freundlicherweise von Stéphane Chazelas in den Kommentaren unten erläutert) ist das
\r
vollständige Deaktivieren mitstty -opost
, obwohl dies höchstwahrscheinlich die Installationbusybox
(oder eine Alternative wie diesetoybox
) auf dem Android-Gerät erfordert.quelle
adb shell 'stty -opost; ls /data/data'
könnte auch funktionieren (wenn dieseCR
eingeführt werden, weiladb
sie mit einem Pseudo-Terminal auf der Android-Seite interagieren).stty raw
beinhaltetstty -opost
was beinhaltetstty -onlcr
. Wenn Sie sich dazu eine Manpage ansehen,adb
können Sieadb shell -t
diese Pty-Zuordnung möglicherweise auch deaktivieren!/system/bin/sh: stty: not found\r$
. Darüber-t
funktioniert es auch nicht :error: target doesn't support PTY args -Tt
. Bitte beachten Sie, dass dies ein ziemlich altes Android-Gerät (4.1) ist.busybox
macht der Trick in der Tat:adb shell 'busybox stty -opost; echo test' | sed -n l
Ausgabentest$
währendadb shell echo test | sed -n l
Ausgabentest\r$
. Vielen Dank!