android: Recursive copy with adb push

AndroidAdb

Android Problem Overview


I think adb's push is file-based. I want to be able to push entire folders. Is there an easy way without scripting?

Thanks!

Edit: I need to work with sub-folders.

Edit: Seems that adb pull is recursive but push is not. So I changed the title and description accordingly.

Android Solutions


Solution 1 - Android

Try this (worked with subfolders):

adb push mySourceFolder/. myDestAndroidFolder

Empty folders do not copy to android device.

Solution 2 - Android

I'm gonna dig this even more to give a full solution to this (for linux only), because google redirect to this and I had this exact same problem.

With a simple adb push, the problem is that all the subdirectories must exist BEFORE doing the push, which can be very painful to achieve.

Note that an easy solution is to zip the folder, push the zip then unzip on the device. But let's say you don't have unzip on your device (highly unlikely, really).

You want to push a full tree with a lot of subdirectories to your device in an empty directory myDirectory. There are two steps :

First create all the subdirectories, in your source device:

cd <folder-containing-myDirectory>
find myDirectory/ -type d -exec adb shell mkdir <path-to-folder-containing-myDirectory-in-device>/{} \;

This command find all the subdirectories of myDirectory (including ., so if myDirectory already exists, you will have one error message you can safely ignore) and for each of them, create the matching directory on the device.

then push everything

adb push myDirectory/. <path-to-folder>/myDirectory

Solution 3 - Android

adb pull, pulls all the files in the specified directory:

$ adb pull /mnt/sdcard/
pull: building file list...
pull: /mnt/sdcard/t3.txt -> ./t3.txt
pull: /mnt/sdcard/t2.txt -> ./t2.txt
pull: /mnt/sdcard/t1.txt -> ./t1.txt
3 files pulled. 0 files skipped.

or

$ adb push . /mnt/sdcard/
push: ./t2.txt -> /mnt/sdcard/t2.txt
push: ./t3.txt -> /mnt/sdcard/t3.txt
push: ./t1.txt -> /mnt/sdcard/t1.txt
3 files pushed. 0 files skipped.

Solution 4 - Android

Ran into this as well and found this article useful, but may have found a more complete solution. Running the following from the folder containing the files/folders you want to push:

adb push . /myDestinationFolder

The key is the prefix '/' before the destination folder apparently. This works from my windows command prompt, but when I run it from git bash (on Windows) I get some errors due to the meaning of the '/' in a path within the bash shell. So this might not work from linux/bash, however it definitely copied all subfolders for me.

Solution 5 - Android

I realize this question is a little old and I'm about to mention scripting when the question excluded it, but I'm going to answer this anyway. Mostly, because I wish I had found this answer here, before having to work it out myself.

adb push WILL work recursively, if all of the subfolders are present already. They can be empty, it just seems that adb push can not make folders. I found this to be a useful distinction because one could run a series of commands like this:

$ adb shell mkdir /folder
$ adb shell mkdir /folder/sub1
$ adb shell mkdir /folder/sub2
$ adb push folder

So, yes, one could make a small wrapper script to do this automatically. However, I think the more important point is that it just requires the folders to be there. Which means that if this is something that you are going to update multiple times in the same folder. For instance, adding pictures to an existing subfolder structure would work great over and over again with the single adb push command.

Solution 6 - Android

To expand on autra's genius answer a bit, I made a quick script to automate this (for Linux/Mac only).

I created an empty file in my home directory called adb-push. Then I edited the file with a text editor (like gedit, nano, vim, etc.) and put the following contents into it:

#!/bin/bash

# Usage:
# adb-push <directory-on-computer-to-send> <directory-on-device-to-receive-it>
# Example:
# adb-push ~/backups/DCIM /sdcard

src="${1}";
trgt="$(basename ${1})";
dst="$(echo "${2}" | grep '/$')";
# If ${dst} ends with '/', remove the trailing '/'.
if [ -n "${dst}" ]; then
	dst="${dst%/*}";
fi;

# If ${src} is a directory, make directories on device before pushing them.
if [ -d "${src}" ]; then
	cd "${src}";
	cd ..;
	trgt="${trgt}/";
    find "${trgt}" -type d -exec adb shell mkdir "${dst}/{}" \;
fi;

adb push "${src}" "${dst}/${trgt}";

Then I made it executable:

chmod +x ~/adb-push;

This is how I run it:

~/adb-push <directory-on-computer-to-send> <directory-on-device-to-receive-it>

For example, if I want to send "~/backups/DCIM" to my device's sdcard folder, I would do this:

~/adb-push ~/backups/DCIM /sdcard

(But keep in mind that the location of the sdcard is not "/sdcard" for every Android device. For instance, it might be "/mnt/sdcard" instead.)

Solution 7 - Android

It has been a few years, the issues may or may not have changed, but it is still a PITA. What is working for me on linux is to create a temp folder, create a symlink to the folder(s) I want to copy, and then I adb push. It ignores the main dir, but copies the subdirs. Currently, I'm not needing to create any subdirs, they do get created and copied for me. That might be platform specific, I'm not sure. But the main dir I'm copying, it copies the files in it instead of the dir. So the temp dir gets ignored, and the symlinked folders then get copied. Example: mkdir tmp cd tmp ln -s ../Foo . ln -s ../Bar . cd .. adb push tmp /sdcard/ And it will push Foo/file1 to /sdcard/Foo/file1 With just adb push Foo/. /sdcard/ then I end up with /sdcard/file1 which doesn't make me happy.

Solution 8 - Android

How about: archive -> push -> extract

Solution 9 - Android

export FOLDER="Books"
TMPIFS="$IFS"
IFS=$'\n'
for i in `find "$FOLDER"/ -type d | sed 's,//\+,/,g'`; do
  adb shell mkdir -p /mnt/sdcard/"$i"
done && \
adb push "$FOLDER"/ /mnt/sdcard/"$FOLDER"
unset FOLDER
IFS="$TMPIFS"

Solution 10 - Android

I couldn't find a solution so I made one:

from ppadb.client import Client as AdbClient
adb = AdbClient(host='127.0.0.1', port=5037)
devices = adb.devices()    #List of all connected devices
import os
import glob

def send_over_adb(device,hostpath,devpath="/storage/emulated/0/"):      # Recursively send folder and files over adb
    if os.path.isfile(hostpath):
        devpath = os.path.join(devpath,hostpath).replace('\\','/') # optimization for windows
        device.push(hostpath, devpath)
    elif os.path.isdir(hostpath):
        for i in glob.glob(hostpath+'\*'):
            print(i)
            send_over_adb(device,i,devpath)
    device.shell('am broadcast -a android.intent.action.MEDIA_MOUNTED -d file:///mnt/sdcard')
    device.shell('am force-stop com.android.gallery3d') #force create thumbnails

This function recursively sends over the folders and files while maintaining folder structure and ignores empty directories.

Limitation: file name shouldn't contain forward or back slashes(idk if any os allows that though)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkakyoView Question on Stackoverflow
Solution 1 - AndroidYura ShinkarevView Answer on Stackoverflow
Solution 2 - AndroidautraView Answer on Stackoverflow
Solution 3 - AndroidDiego Torres MilanoView Answer on Stackoverflow
Solution 4 - AndroidCorey PendletonView Answer on Stackoverflow
Solution 5 - Androiduser1449536View Answer on Stackoverflow
Solution 6 - AndroidGreenRaccoon23View Answer on Stackoverflow
Solution 7 - AndroidRubyPantherView Answer on Stackoverflow
Solution 8 - AndroidSharasView Answer on Stackoverflow
Solution 9 - AndroidmutanabbiView Answer on Stackoverflow
Solution 10 - AndroidRajarshi Ghosh DastidarView Answer on Stackoverflow