104

What is the best way to pull multiple files using

adb pull

I have on my /sdcard/ 25 files with following name:

gps1.trace
gps2.trace
...
gps25.trace

Wildcard does not work:

adb pull /sdcard/gps*.trace .
hsz
  • 148,279
  • 62
  • 259
  • 315
  • 5
    I don't use `adb` but from the docs `pull` can be used to pull an entire directory??? If that's the case and these are files generated by your own app then why not write them out to a sub-directory such as `/sdcard/mygpsfiles` and then use `adb pull /sdcard/mygpsfiles`. Would that work? – Squonk Jun 17 '12 at 21:25
  • 2
    Alternatively, I've just tried the File Explorer in the `DDMS` perspective of eclipse and was able to multi-select files from my sdcard and perform a `pull` on them. If you don't use eclipse, DDMS is available as a separate SDK tool. – Squonk Jun 17 '12 at 21:35
  • `monitor` command works great, should be in `/tools`! – Santosh Kumar Sep 05 '13 at 12:41

16 Answers16

154

You can use xargs and the result of the adb shell ls command which accepts wildcards. This allows you to copy multiple files. Annoyingly the output of the adb shell ls command includes line-feed control characters that you can remove using tr -d '\r'.

Examples:

# Using a relative path
adb shell 'ls sdcard/gps*.trace' | tr -d '\r' | xargs -n1 adb pull
# Using an absolute path 
adb shell 'ls /sdcard/*.txt' | tr -d '\r' | sed -e 's/^\///' | xargs -n1 adb pull
jox
  • 2,218
  • 22
  • 32
David Momenso
  • 1,931
  • 1
  • 12
  • 10
  • actually those are carriage returns which must be filtered, but right idea on an obscure issue – Chris Stratton Jun 28 '12 at 18:28
  • 5
    Here's a slightly improved version that can handle spaces in file names: https://github.com/sschuberth/dev-scripts/blob/master/android/pull_all.sh – sschuberth Nov 26 '13 at 15:50
  • FYI: Windows and DOS use "\r\n" for carriage-return / line-feed pairs (i.e. not "\n\r"). – BrainSlugs83 Jan 19 '14 at 23:34
  • 3
    in my case it failed trying to pull the (correctly obtained) filenames from the android's root directory, to solve it, I used: `adb shell "ls -d /mnt/sdcard/Pictures/Screenshots/*" | tr '\r' ' ' | xargs -n1 adb pull` – rupps Sep 17 '14 at 12:29
  • I had to use `find` instead of `ls` because paths starting with `/` didn't work and ones without `/` returned just filename, without full path. (Windows/msys) – gronostaj Feb 03 '15 at 13:33
  • It's true that the newline in windows is \n\r, but there's no build-in "tr" or "xargs" command in batch. – wrkwrk Jul 22 '15 at 05:24
  • See my answer below for a slightly modified version that allows you to pull into remote directories and is slightly more terse – FuriousGeorge May 09 '16 at 17:47
  • I found your answer useful, but I wondered why you didn't just do `tr -d '\r'`. – starfry Jun 10 '16 at 20:16
  • 6
    It doesn't work saying *tr is not recognized as an internal or external command* – Suncatcher Jan 08 '17 at 09:50
  • `tr` is an application present in Linux or git bash. – Bruno Alexandre Rosa Oct 16 '17 at 09:16
  • I wrote a bash function expanding on this answer to allow me to pass in a parameter to combine with the * `function vids () { adb shell 'ls /sdcard/DCIM/Camera/VID_2022'"$1"'*.mp4' | tr -d '\r' | sed -e 's/^\///' | xargs -n1 adb pull }` Usage: vids 1028 Result: Pulls all the videos from 2022/10/28 – DroidClicketyClacker Oct 28 '22 at 16:56
111

adb pull can receive a directory name instead of at file and it will pull the directory with all files in it.

Pull all your gps traces in /sdcard/gpsTraces

adb pull /sdcard/gpsTraces/ . 

Example of adb pull and adb push of recursive directories:

C:\Test>adb pull /data/misc/test/ .
pull: building file list...
pull: /data/misc/test/test1/test2/test.3 -> ./test1/test2/test.3
pull: /data/misc/test/test1/test2/test.2 -> ./test1/test2/test.2
pull: /data/misc/test/test1/test2/test.1 -> ./test1/test2/test.1
pull: /data/misc/test/test1/test.3 -> ./test1/test.3
pull: /data/misc/test/test1/test.2 -> ./test1/test.2
pull: /data/misc/test/test1/test.1 -> ./test1/test.1
pull: /data/misc/test/test.3 -> ./test.3
pull: /data/misc/test/test.2 -> ./test.2
pull: /data/misc/test/test.1 -> ./test.1
9 files pulled. 0 files skipped.
0 KB/s (45 bytes in 0.093s)

C:\Test>adb push . /data/misc/test/
push: ./test1/test2/test.3 -> /data/misc/test/test1/test2/test.3
push: ./test1/test2/test.2 -> /data/misc/test/test1/test2/test.2
push: ./test1/test2/test.1 -> /data/misc/test/test1/test2/test.1
push: ./test1/test.3 -> /data/misc/test/test1/test.3
push: ./test1/test.2 -> /data/misc/test/test1/test.2
push: ./test1/test.1 -> /data/misc/test/test1/test.1
push: ./test.3 -> /data/misc/test/test.3
push: ./test.2 -> /data/misc/test/test.2
push: ./test.1 -> /data/misc/test/test.1
9 files pushed. 0 files skipped.
0 KB/s (45 bytes in 0.062s)
lid
  • 786
  • 8
  • 13
Ofir Luzon
  • 10,635
  • 3
  • 41
  • 52
  • 3
    @kakyo It does work for subfolders for me. check you have the latest ADB from google. (I'm using 1.0.29) – Ofir Luzon Oct 31 '12 at 12:24
  • Yes, I found that it works for non-empty folders in the end. I had some empty folders that didn't get pulled. Also, seems that "push" is non-recursive? – kakyo Oct 31 '12 at 21:09
  • @kakyo I've added the output of a recursive pull and push to my answer. You are correct about empty folders, they do not get pulled or pushed. – Ofir Luzon Nov 01 '12 at 07:05
  • 1
    Beware: with ADB pull the files lose their original modified date. – Stan Feb 20 '16 at 09:10
  • 3
    @Stan: unless you use the "-a" option as in "adb pull [-a] ... ", which according to the help preserves the file timestamp and mode. – Rusty Gear Aug 27 '16 at 11:52
28

./adb pull /sdcard <-- fails

./adb pull /sdcard/ <-- works recursively - note the trailing slash

Tested with Nexus 5 and adb downloaded March 2014.

lalibi
  • 3,057
  • 3
  • 33
  • 41
17

Parsing the output from 'ls' is generally a bad idea. Instead, use 'find'.

adb shell 'find /sdcard/ -name "gps*.trace" -print0' | xargs -0 -n 1 adb pull

Why you shouldn't parse the output of ls

ishmael
  • 1,796
  • 3
  • 18
  • 19
7

I have created this for Windows boxes, It is very useful to transfer files using wildcards without mounting the filesystem. You can include this script somewhere in your path env.

adbpull.bat

@echo off
setlocal enabledelayedexpansion
if %1.==. (
    echo Wilcard parameter is required.
    goto end
)
for /F "tokens=* USEBACKQ" %%F in (`adb shell ls %1`) do (
    set text=%%F
    set mfile=!text:~0,-1!
    adb pull "!mfile!"
)
:end
endlocal

Example: adbpull /sdcard/DCIM/Camera/IMG_2016*

lalibi
  • 3,057
  • 3
  • 33
  • 41
cardeol
  • 2,218
  • 17
  • 25
6

Even though adb pull command started accepting folder name for the remote parameter, I still prefer to use tar command. It provides more flexibility - allows for file name patterns (both include and exclude), symlink control, preserves file permissions. Since Android 6.0 you can use a built-in. Before that you had to use 3rd-party tools like busybox:

adb exec-out tar c sdcard/amazonmp3 > amazon.tar

Make sure to omit the leading / in your path.

Alex P.
  • 30,437
  • 17
  • 118
  • 169
themuddler
  • 61
  • 1
  • 1
  • Oh, it didn't work. tar -tvf tells me that the result doesn't look like a tar archive. Oh well. – themuddler Feb 18 '13 at 11:08
  • Very strong way! But the problem is errors/warnings like "tar: removing leading '/' from member names" added to output file. Don't know how to eliminate this. – x'ES May 23 '17 at 06:52
  • I get 1.5KB file on the output. – Shayan Jan 29 '20 at 15:49
  • Heads up! You need to redirect stderr to somewhere else or you might get a corrupted tar file! See https://askubuntu.com/a/170000 for reason, and at least test if the result file is not corrupted. – Gary Wang Jun 05 '22 at 06:54
4

ADBFS a FUSE Filesystem for Android Debug Bridge if you are using linux or mac

qdiesel
  • 401
  • 3
  • 9
  • Unfortunately I am using Windows with Cygwin. But I have to remember this one - very interesting solution ! – hsz Jun 17 '12 at 20:52
4

Directory pull is available on new android tools. ( I don't know from which version it was added, but its working on latest ADT 21.1 )

adb pull /sdcard/Robotium-Screenshots
pull: building file list...
pull: /sdcard/Robotium-Screenshots/090313-110415.jpg -> ./090313-110415.jpg
pull: /sdcard/Robotium-Screenshots/090313-110412.jpg -> ./090313-110412.jpg
pull: /sdcard/Robotium-Screenshots/090313-110408.jpg -> ./090313-110408.jpg
pull: /sdcard/Robotium-Screenshots/090313-110406.jpg -> ./090313-110406.jpg
pull: /sdcard/Robotium-Screenshots/090313-110404.jpg -> ./090313-110404.jpg
5 files pulled. 0 files skipped.
61 KB/s (338736 bytes in 5.409s)
Palani
  • 8,962
  • 11
  • 53
  • 62
2

building on David's answer, I find this to be slightly better:

adb shell ls /foo | tr -d '\r' | xargs -n1 adb pull

In addition to it being one character less to type (big deal) it doesn't convert the -r into a space. This is a significant difference, as if you try to do

adb shell ls /foo/myFile* | tr '\r' ' ' | xargs -i -n1 adb pull {} someDir

you'll get error saying

remote object '/foo/myFile1 ' does not exist

Instead you can do this, which will work:

adb shell ls /foo/myFile* | tr -d '\r' | xargs -i -n1 adb pull {} someDir 
FuriousGeorge
  • 4,561
  • 5
  • 29
  • 52
2

PowerShell:

adb shell ls /sdcard/gps*.trace | foreach {adb pull $_}

samus
  • 6,102
  • 6
  • 31
  • 69
0

Wild cards work in my case, I have been using following simple script to import Whatsapp Images of my virtual device in to my desktop

#! /bin/bash
mkdir -p ~/Pictures/Pictures_adb
rm -f ~/Pictures/Pictures_adb/*
cd ~/Pictures/Pictures_adb
adb root
adb shell 'cp /data/media/0/WhatsApp/Media/WhatsApp\ Profile\ Photos/* /sdcard/Pictures/;exit'
adb pull /sdcard/Pictures
mv ~/Pictures/Pictures_adb/Pictures/* ~/Pictures/Pictures_adb/
rmdir ~/Pictures/Pictures_adb/Pictures
cd
srinivasu u
  • 1,393
  • 11
  • 12
  • You use wildcards for cp on Android and not for pull on the host, that's why it works. Nice alternative, though copying to /sdcard/ costs extra memory and leaks private files to sdcard. – user905686 May 14 '18 at 12:06
0

This is possible using adb exec-out. For example to get all of today's screenshots you can do:

adb exec-out "cd /sdcard/Pictures/Screenshots; tar c Screenshot_20210907*" | tar x

This will transfer all of the files inside a temporary tar archive and extract it to your current working directory. Credit is due to https://stackoverflow.com/a/39429196/3347392.

0

I wanted to expand on David Momenso's answer and address the specific part of the question about wildcards. I turned his suggestion into a bash function that will allow for passing in a parameter that will append to the wildcard.

This a bash function that will allow for pulling all videos based on the date, utilizing the passed in parameter and wildcard.

function vids () { adb shell 'ls /sdcard/DCIM/Camera/VID_2022'"$1"'*.mp4' | tr -d '\r' | sed -e 's/^\///' | xargs -n1 adb pull }

  • /sdcard/DCIM/Camera/VID_2022 is pointing to the Camera folder and has the file prefix that accounts for the current year
  • "$1" is take the first parameter that comes after the function call
    • 1027 in the example usage vids 1027

enter image description here

DroidClicketyClacker
  • 2,057
  • 1
  • 10
  • 10
0

I am using Windows adb.exe and gitbash, even syntax is right, adb.exe says it cannot find files if used in xargs.

You have to use cmd for loop:

for /f "delims=" %G in ('adb shell find sdcard/DCIM/Camera/20221111*') do adb pull -a "%G"

This will download all photos and videos matching the criteria(in my case, taken on the day 2022 Nov 11st).

Find more info googling for /f and linux find.


If you don't have find available(Gitbash not installed), a workaround is to move all files you want on phone to another new album and adb pull from there. Not a solution but a workaround.

adb pull -a sdcard/DCIM/new-album . # will pull all photos to a folder called "new-album"
WesternGun
  • 11,303
  • 6
  • 88
  • 157
0

I used this:

adb pull $(adb shell ls /storage/9016-4EF8/DCIM/Camera/wildcard*) ./

user2195463
  • 321
  • 5
  • 8
-3

In Android, there are some folder with associated permissions! Some folder belong to root- or system user.

You guys should change the permissions of those files, folders before doing "adb pull".

The following commands could help:

adb shell
su
chmod -R 777 target_folder
exit
...
adb pull /.../target_folder/ . (current local folder)
Tim Long
  • 2,039
  • 1
  • 22
  • 25