strange behaviour of adb pull in bash script

2019-05-11 00:23发布

问题:

I want to write a bash script to fetch all WhatsApp's backups automatically, but I cannot understand what's wrong

#!/bin/bash

adb start-server
for file in $(adb shell ls /sdcard/WhatsApp/Databases) 
do
    adb pull /sdcard/WhatsApp/Databases/$file
done

The output is very strange:

$ ./script.sh
' does not existsdcard/WhatsApp/Databases/msgstore-2014-10-28.1.db.crypt7
' does not existsdcard/WhatsApp/Databases/msgstore-2014-10-29.1.db.crypt7
' does not existsdcard/WhatsApp/Databases/msgstore-2014-10-30.1.db.crypt7
' does not existsdcard/WhatsApp/Databases/msgstore-2014-11-01.1.db.crypt7
' does not existsdcard/WhatsApp/Databases/msgstore-2014-11-02.1.db.crypt7
' does not existsdcard/WhatsApp/Databases/msgstore-2014-11-03.1.db.crypt7
' does not existsdcard/WhatsApp/Databases/msgstore-2014-11-04.1.db.crypt7
' does not existsdcard/WhatsApp/Databases/msgstore.db.crypt7

since "adb shell ls /sdcard/WhatsApp/Databases" works, there shall be no problem pulling each file into the current working directory, but as you can see, even the error message doesn't look well formed ("' does not existsdcard/WhatsApp...")

I tried echo "adb pull /sdcard/WhatsApp/Databases/$file" instead of directly calling adb, and if I copy/paste each single line of the output into the shell, it works. But any other attempt to do this automatically fails.

I feel like if I forgot some very basic concepts of bash scripting

Edit: After running it with

#!/bin/bash -x

(thanks to Rakesh Gupta suggestion) the output is the following:

+ adb start-server
++ adb shell ls /sdcard/WhatsApp/Databases
+ for file in '$(adb shell ls /sdcard/WhatsApp/Databases)'
+ adb pull $'/sdcard/WhatsApp/Databases/msgstore-2014-10-28.1.db.crypt7\r' .
remote object '/sdcard/WhatsApp/Databases/msgstore-2014-10-28.1.db.crypt7' does not     exist
+ for file in '$(adb shell ls /sdcard/WhatsApp/Databases)'
+ adb pull $'/sdcard/WhatsApp/Databases/msgstore-2014-10-29.1.db.crypt7\r' .
remote object '/sdcard/WhatsApp/Databases/msgstore-2014-10-29.1.db.crypt7' does not exist
+ for file in '$(adb shell ls /sdcard/WhatsApp/Databases)'
+ adb pull $'/sdcard/WhatsApp/Databases/msgstore-2014-10-30.1.db.crypt7\r' .
remote object '/sdcard/WhatsApp/Databases/msgstore-2014-10-30.1.db.crypt7' does not exist
+ for file in '$(adb shell ls /sdcard/WhatsApp/Databases)'
+ adb pull $'/sdcard/WhatsApp/Databases/msgstore-2014-11-01.1.db.crypt7\r' .
remote object '/sdcard/WhatsApp/Databases/msgstore-2014-11-01.1.db.crypt7' does not exist
+ for file in '$(adb shell ls /sdcard/WhatsApp/Databases)'
+ adb pull $'/sdcard/WhatsApp/Databases/msgstore-2014-11-02.1.db.crypt7\r' .
remote object '/sdcard/WhatsApp/Databases/msgstore-2014-11-02.1.db.crypt7' does not exist
+ for file in '$(adb shell ls /sdcard/WhatsApp/Databases)'
+ adb pull $'/sdcard/WhatsApp/Databases/msgstore-2014-11-03.1.db.crypt7\r' .
remote object '/sdcard/WhatsApp/Databases/msgstore-2014-11-03.1.db.crypt7' does not exist
+ for file in '$(adb shell ls /sdcard/WhatsApp/Databases)'
+ adb pull $'/sdcard/WhatsApp/Databases/msgstore-2014-11-04.1.db.crypt7\r' .
remote object '/sdcard/WhatsApp/Databases/msgstore-2014-11-04.1.db.crypt7' does not exist
+ for file in '$(adb shell ls /sdcard/WhatsApp/Databases)'
+ adb pull $'/sdcard/WhatsApp/Databases/msgstore.db.crypt7\r' .
remote object '/sdcard/WhatsApp/Databases/msgstore.db.crypt7' does not exist

and indeed there is the \r character at the end of each file name that is likely to cause that behaviour.

Thanks to that other guy that linked me to https://stackoverflow.com/tags/bash/info, and adding "tr -d '\r'", in this way the script runs nicely

#!/bin/bash 

adb start-server

for file in $(adb shell ls /sdcard/WhatsApp/Databases | tr -d '\r')
do
    adb pull /sdcard/WhatsApp/Databases/$file .
done

回答1:

There may be a special character in you script. Try running dos2unix on your script. Also, try adding -n as under to check the syntax

#!/bin/bash -n

and run the script to identify any issues with syntax.

You can also try

#!/bin/bash -x 

to enable the debug mode