xargsが正しいコマンドを生成しない

xargsが正しいコマンドを生成しない

私のAndroidデバイスから同じパッケージで始まる複数のアプリを削除したいです。次のコマンドでこれを取得します。

$ 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

それでは、各パッケージ名に対してこれを行いたいと思います。adb uninstall次を使用しようとしましたxargs

$ 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

うまくいきそうなので削除しましたecho

$ adb shell ls /data/data | grep -i com.company | xargs -n1 adb uninstall
Failure
Failure
Failure
Failure
Failure

ただし、各コマンドを独立して実行すると、次のようになりますSuccess

$ adb uninstall com.company.android.app.adwidget
Success

私は何が間違っていましたか?

答え1

質問は最終的にadb shell出力のCR文字が原因で発生(ターゲットAndroidシステムで生成されたptyのttyラインルールを介して挿入されます(参照)ここ詳しくは))もう一つの可能​​な説明(よくある質問なので今後読者のために残しておきますxargs)は次のとおりです。

adb shell ls /data/data | grep -i com.company | xargs -n1 adb uninstall

xargs実装に応じて、adb標準入力は/dev/nullパイプまたはパイプから出ますgrep。とにかくttyではないadbので、ユーザーと対話できると予想されると失敗する理由かもしれません。

GNUxargsとプロセスの交換をサポートするシェル(例zsh:)を使用すると、次のように変更できます。

xargs -n1 -ra <(adb shell ls /data/data | grep -i com.company) adb uninstall

この場合、xargs引数として提供されたファイルからリストを読み取るので、-astdinをそのまま残すことができます。

または言及した後、次のものをzsh使用できます。

autoload zargs # best in ~/.zshrc
zargs -L1 $(adb shell ls /data/data | grep -i com.company) -- adb uninstall

-L代わりに制限を使用してください-nzargs-nみんな引数の数adb(1つを含むuninstall、つまりが必要であることを意味する-n 2)。

あるいは、単にループを使用すると、より短くて明確になります。

for x ($(adb shell ls /data/data | grep -i com.company)) adb uninstall $x

答え2

出力をadb shell ls /data/data | grep -i com.companyファイルにリダイレクトし、16進エディタを使用して調べたところ、Windowsスタイルのキャリッジリターンが追加されたことがわかりました\r\n (0x0D 0x0A)。だから削除すると問題が解決します\rtr -d '\r'

完全なコマンドはfor(fromStefan Chazerasの答え):

for x in $(adb shell ls /data/data | grep -i com.company | tr -d '\r'); do adb uninstall $x;  done

または同様に使用してくださいxargs

adb shell ls /data/data | grep -i com.company | tr -d '\r' | xargs -r -n1 adb uninstall

別のオプション(Stéphane Chazelasが以下の説明で親切に説明したように)\rを完全に無効にすることですstty -opost。ただし、この場合、Androidデバイスbusybox(または同様の代替手段)にインストールする必要がある可能性が高くなります。toybox

$ adb shell echo test | sed -n l               
test\r$
$ adb shell 'busybox stty -opost; echo test' | sed -n l
test$

関連情報