I wrote a little script to do this for me that deletes files from the device after pulling:
#!/bin/sh
cleanup() {
[[ -n "$dest" ]] && cd "$OLDPWD" && rmdir --ignore-fail-on-non-empty "$dest"
}
trap cleanup EXIT
DIRS=( /storage/emulated/0/DCIM/Camera
/storage/emulated/0/Pictures/Office\ Lens )
dest=$(mktemp -d -p .) && cd $dest
echo output directory: $(pwd)
for dir in "${DIRS[@]}"
do
echo downloading from $dir
adb shell ls "'$dir'/*.jpg" 2>/dev/null | xargs -I{} -n 1 -d '\n' sh -c 'adb pull -a "$1" && adb shell rm "\"$1\"" && adb shell am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d \"file://$1\" || exit 255' -- {} || break
done
The main process is a loop executed once for each directory $dir
specified in $DIRS
that terminates on the first failure.
The break
prevents processing in the event of an error so that the script exits on the first failure.
The loop executes a compound command for each directory listed in $DIRS
as $dir
. The first piece is straightforward:
ls "'$dir'/*.jpg" 2>/dev/null
It does what it says on the tin - lists all of the JPEG files located at $dir
. The 2>/dev/null
hides the No such file or directory
error message that would otherwise be displayed when there are no such files.
The output of ls
is piped into xargs
- the arguments set {}
as the placeholder, \n
as the delimiter and processes files one at a time. The command line used to process each file follows:
sh -c 'adb pull -a "$1" && adb shell rm "\"$1\"" && adb shell am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d \"file://$1\" || exit 255' -- {}
Which is itself a compound command of three adb
commands executed by a sh
shell which is given the file as an argument ($1
) specified by its {}
placeholder.
The first command downloads the file:
adb pull -a "$1"
If that succeeds then the second command removes the file from the Android device:
adb shell rm "\"$1\""
The extra quoting is necessary so that file names containing white space are properly passed into the adb shell
. If that command succeeds then the final command lets the device know the file is gone:
adb shell am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d \"file://$1\"
Once again, quoting is applied for adb shell
. This step is required to update the images listed in the Gallery app (otherwise they may be cached and still display).
The compound command finishes with exit 255
in the event that any of the adb
commands fail. This has special meaning to xargs
and causes it to terminate without processing any more files.
This is a quick and dirty script - it could probably be improved but hopefully it's helpful as it is.