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.
Try this (worked with subfolders):
adb push mySourceFolder/. myDestAndroidFolder
Empty folders do not copy to android device.
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
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.
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.
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.
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.)
How about: archive -> push -> extract
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.
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"
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)
Related
I have a simple bash script to push an executable to the android and then remove it.
#!/bin/bash
adb push CMakeBuild_Android_armv8/Out/Release/exec /data/local/tmp/exec
adb shell rm data/local/tmp/exec
This is saved as 'adb_push.sh'. I made sure that this is an executable via chmod.
chmod +x adb_push.sh
But when I run this script in the Cygwin ./adb_push.sh, I get an error that there is no such directory.
CMakeBuild_Android_armv8/Out/Release/exec: 1 file pushed, 0 skipped. 62.5 MB/s (7302616 bytes in 0.111s)
rm: data/local/tmp/exec: No such file or directory
Is there any obvious steps that I am missing in creating a bash script or is there any error in what I am doing?
Any hint or comment would be highly appreciated.
ADB version:
$ adb version
Android Debug Bridge version 1.0.41
Version 31.0.0-7110759
Installed as C:\platform-tools_r31.0.0-windows\platform-tools\adb.exe
Disclaimer: I already tried putting the source and destination path in quotes, it did not work for me. Also tried the same with a .wav file instead of an executable and I get the same error which lead me to believe that something's not right in the bash script.
Your second command assumes the working directory is the root /. It appears this assumption is false.
The first command is succeeding. Only the second command is failing.
If adb shell doesn't start at the root (/), then the destination path you supply in the first command (/data/local/tmp/exec) is different from the path you supply in the second command (data/local/tmp/exec, note the missing slash at the beginning).
I'm gonna guess adb shell on your device starts a shell in some user's home directory, not /.
Option 1: Use absolute file path
You can fix this by giving the full absolute file path in your second command:
adb shell rm /data/local/tmp/exec
Option 2: Change directories before your command
Alternatively, you can change to the root directory before running the command. adb shell (as of version 31.0.0-7110759) does not have the ability to set the working directory, but you can do this inside the shell by adding a cd before your rm. Note that the command must now be quoted to prevent your local shell from interpreting the list operator &&:
adb shell 'cd / && rm data/local/tmp/exec'
Note: The adb shell default working directory may vary by device or ROM. On my stock Pixel 3 it does in fact start at the root:
$ adb shell pwd
/
I'm using ADB in order to copy files from my desktop to a folder on my emulator.
adb push pic.jpg '/storage/emulated/0/DCIM/camera/
This works fine, but I have many files I would like to copy, and I don't want to repeat this command for every file. How can I "push" the contents of a whole directory?
Edit: screenshot of my Android studio:
For uploading the whole directory, the easiest way is to use Device File Manager in Android Studio.
Open it from the bottom right toolbar and navigate to the directory in the device where you want to upload the data.
Right click and click on upload to upload files or directory.
Note: Works only in Android Studio 3.0 and above
To push everything in the current directory, you can try:
adb push * /storage/emulated/0/DCIM/camera/*
You could use tar to put all your files into a single archive:
tar -cvf all.tar .
Then push that archive to the device:
adb push all.tar /sdcard
Finally untar your tar file in the device:
adb shell tar -xvf /sdcard/all.tar -C /sdcard
I couldn't find a solution so I made one:
from ppadb.client import Client as AdbClient
import os
import glob
adb = AdbClient(host='127.0.0.1', port=5037)
devices = adb.devices() #List of all connected devices
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
hostpath='\path\to\folder\or\file\'
send_over_adb(devices[0],hostpath,devpath)
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)
Dependency: pure-python-adb
Tested on: Python3.7.9 on Win 8.1
I pushed a bunch of files on Android sdcard using adb
adb push local_path/directory/ device_path/directory/
But, once it has pushed all the files, when I counted the number of files on both the computer and the android device, I found more files on Android than actual files on the machine.
machinex:My_Tools user$ adb shell ls -R /device_path/directory/ | wc -l
36624
machinex:My_Tools user$ ls -R /local_path/directory/ | wc -l
36617
I tried deleting the directory on Android device, and pushing all the files again, but with same result.
Does anyone have any idea, what may be causing the difference. Are there some hidden files on android, that are generated at their own ?
You can try ls -a command in the so named directory of your board. This will list both hidden and non hidden files in that respective folder.
Steps:
1) adb shell
2) once you are in the board's shell,
cd /path/to/yourdirectory/
3) ls -a
hope this helps you :)
When I run below command directly on prompt, it works fine by pulling all files from emulator sdcard:
adb -s emulator-5556 pull /sdcard/.
However when I create bash file (extract.sh) with above command and run it I get following error:
remote object 'C:/Program Files (x86)/Git/sdcard/' does not exist
As can be seen it somehow adds C:/Program Files (x86)/Git before it. These are the contents of bash file:
#!/bin/bash
adb -s emulator-5556 pull /sdcard/.
Does anyone have an idea of why it works when direcly typing on prompt and not via bash file ? Thanks
Is there any reason you're not specifying the destination directory? For example, the batch command I use when pulling pictures from my phone over USB is adb pull "/sdcard/DCIM/Camera" "E:\Phone Pics\HTC DNA" which specifies both the source directory on the phone and the destination directory on my computer. As a side note, like enedil I recommend using this in a batch file when working in Windows.
I need get SQLite database from Android app from Genesis device where user has populated by hand.
How I can create another app or any other way to get this db and save in place where I can get?
obs.: the device has root
Thanks
Steps from .../platform-tools of Android on cmd:
1) type adb shell
2) run-as com.your.package
3) type ls
cache
databases
lib
You can find Your Database Here...Also You didn't even have to root the Device
Hope this could helpful for you...
Provided you have the device attached to a box with adb on the PATH you can use this command:
adb -d shell 'run-as your.package.name.here cat /data/data/your.package.name.here/databases/your_db_name_here.sqlite > /sdcard/recovered_db.sqlite'
Or you can use Ecliplse DDMS file explorer.
VERY EASY WAY TO DO IT
In the latest releases of Android Studio (I am using AS v3.1.2) the Google team has made it really straight forward. You just have to open the Device File Explorer window which should be at the bottom of the right vertical toolbar, if you cannot find it you can also open it this way:
View -> Tool Windows -> Device File Explorer
Once you have Device File Explorer window open, use your mouse to navigate to the following path:
data -> data -> your.package.name -> databases
Inside the databases folder you should see the database you want to explore, do a right click and Save As... select your desired computer destination folder and voila!!
You can either include the Stetho library on your app,
http://facebook.github.io/stetho/
which will allow you to access your DB using Chrome's Web Debug tools
or use the following shell script:
#!/bin/bash
echo "Requesting data from Android"
adb backup -f data.ab -noapk YOUR.APK.NAME
echo "Decoding...."
dd if=data.ab skip=24 iflag=skip_bytes | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" | tar -xvf -
rm data.ab
echo "Done"
```
None of the methods above require your device to be rooted and the latter works even on apps that you did not write yourself, as long as the ApplicationManifest.xml does not contain "backup=false"
After trying dozens of commands that didn't work for me on Marshmallow, I've found this one that works (for debuggable apps at least):
adb shell "run-as your.package.name cp /data/data/your.package.name/databases/you-db-name /sdcard/file_to_write"
Then you simply can view the DB with aSQLiteManager for instance.
You can use this script.
humpty.sh
You should know the application package name and sqlite database name.
You can check the available databases.
$ adb shell
$ run-as <package-name>
$ ls databases/
To dump database or other file.
./humpty.sh -d <package-name> databases/<db-name>