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로 사용자와 상호 작용할 수 있을 것으로 예상되면 실패하는 이유일 수 있습니다.

GNU xargs와 프로세스 교체를 지원하는 셸(예: 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대신 제한을 사용 하십시오 -n.zargs-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). 그래서 제거하면 문제가 해결됩니다 \r.tr -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$

관련 정보