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 am trying to delete the file using adb command. But the file contain spaces. So adb command throws an error after reading half of the file name till space. Is there a way to overcome this issue. I am executing following adb command
When I execute
adb shell rm /sdcard/samsung_Nexus S_converter.xml
Error message: rm failed for /sdcard/samsung_Nexus, No such file or directory
How ever when I execute:
adb shell rm /sdcard/samsung_Nexus_S_converter.xml
File deletion is successful
I searched for solution for this, if there is any workaround. How ever I couldnt find any.
Since you are using command line, you need to know that spaces must be escaped by using (backslash before the special character like "space"), so, in your case this should work too:
adb shell rm /sdcard/samsung_Nexus\ S_converter.xml
Hope it helps!
Regards!
By me it wasn't enough to escape spaces with backslashes:
$ adb shell ls /storage/sdcard1/audio/Die\ Toten\ Hosen/
/storage/sdcard1/audio/Die: No such file or directory
Toten: No such file or directory
Hosen/: No such file or directory
For some reason I also had to surround the path with ' (single quotation):
$ adb shell ls '/storage/sdcard1/audio/Die\ Toten\ Hosen/'
03 - Boxed Set
04 - Compilations
05 - Live Albums
While surrounding without escaping didn't work:
$ adb shell ls '/storage/sdcard1/audio/Die Toten Hosen'
/storage/sdcard1/audio/Die: No such file or directory
Toten: No such file or directory
Hosen: No such file or directory
Did you tried escaping the space
adb shell rm /sdcard/samsung_Nexus\ S_converter.xml
I have a couple of shell scripts stored in the /Scripts folder of my AppleScript application.
I can access them by setting my base path
set basePath to POSIX path of ((path to me as text)) & "Contents/Resources/Scripts/"
But I'm only able to run the script if I call the Terminal app
-- This works
tell application "Terminal"
set currentTab to do script (basePath & "install_key.sh")
end tell
-- This does not work
do shell script basePath & "install_key.sh"
The error on do shell script complains about not being able to find adb (Android Debug Bridge)
FWIW, here is the shell script in question (install_key.sh)
#!/bin/bash
#Find script directory
DIR="$( cd "$( dirname "$0" )" && pwd )"
adb push $DIR"/key-dev.txt" /sdcard/ &&
adb shell mv /sdcard/key-dev.txt /sdcard/key.txt
Problem
If I understand correctly, your main issue is that your script cannot detect and hold the presence of a specific command located on a system.
Solution
I believe the following code will be effective in helping you achieve your goal. This applescript allows you to find whether ADB is stored on a system and store it's path in a variable. You can add the variable to your path and export as others have suggested or have a look at the export process in Apple's TN2065.
If ADB is not found on a system then users can receive a prompt telling them what actions to take (if that aligns with your use-case or you could begin the install sequence for ADB). To test the behavior of the script you can simply change the adp to some other (fake) command that does not exist on your system. I've added the path to the dialog so that you can see the do shell is passing the contents of the which command into a variable.
try
set adbPath to do shell script "which adb"
on error errStr number errorNumber
-- If our own error number, warn about bad data.
if the errorNumber is not equal to 0 then
display dialog "ADB is not loaded onto system. Please load ADB and run this app again"
return 0 -- Return the default value (0).
else
-- An unknown error occurred. Resignal, so the caller
-- can handle it, or AppleScript can display the number.
error errStr number errorNumber
end if
end try
if length of adbPath > 0 then display dialog "ADB found continue processing..." & adbPath
The structure defined in the TN2065 above is essentially:
$ VAR=something; export VAR $ osascript -e 'do shell script "echo $VAR"' something
You might also want to try the administrator option when calling the shell script:
do shell script "command" user name "me" password "mypassword" with administrator privileges
The Technical Note TN2065: do shell script in AppleScript is the key reference for this kind of issues.
when you use just a command name instead of a complete path, the shell
uses a list of directories (known as your PATH) to try and find the
complete path to the command. For security and portability reasons, do
shell script ignores the configuration files that an interactive shell
would read, so you don’t get the customizations you would have in
Terminal.
First: find the full path of adb
you have to open a Terminal and issue the following command:
$ which adb
suppose the response is:
/Users/ronda/projects/android/sdk/platform-tools/adb
this means that the path of adb is:
/Users/ronda/projects/android/sdk/platform-tools
, now we have several way to address the problem, for example follow one of these two options:
Option1: Fix the AppleScript
do shell script "PATH=${PATH}:/Users/ronda/projects/android/sdk/platform-tools; export PATH; echo $PATH; " & basePath & "install_key.sh"
Option2: Fix the shell script
for example you could specify full path to the adb command in your .sh this way:
#!/bin/bash
#Find script directory
DIR="$( cd "$( dirname "$0" )" && pwd )"
/Users/ronda/projects/android/sdk/platform-tools/adb push $DIR"/key-dev.txt" /sdcard/ &&
/Users/ronda/projects/android/sdk/platform-tools/adb shell mv /sdcard/key-dev.txt /sdcard/key.txt
The simplest solution would be running the same bash configuration as your terminal application. The main difference is that Terminal uses an interactive bash and do shell script command doesn't. To run an interactive shell you can simply execute a new one with option -i (stands for interactive). When an interactive shell is opened the ~/.bashrc file is used, while non-interactive shells don't use this file.
do shell script "bash -i <<<" & quoted form of (basePath & "install_key.sh" as text)
if you don't like that you can simply execute the bashrc file or read the path variable and set it in a do shell script.
I have been attempting to write a script to harden android. I have had no success!
I am running a AVD via emulator and have tried this with both the android shell and bash shell which i loaded. The script is simple as you will see below and each command runs fine independently but in a script it just runs through too fast or something.
I know there's no shebang at the top but that's because of errors when i inserted one.
my script is:
echo ANDROID
echo HARDENING STARTED
device=/dev/block/mtdblock0
mount -o rw,remount $device /system
#removing files in the /system/xbin directory
rm /system/xbin/tcpdump
rm /system/xbin/su
#removing files in the /system/bin directory
rm /system/bin/bootanimation
rm /system/bin/dumpstate
rm /system/bin/ping
rm /system/bin/ping6
echo ANDROID
echo HARDENING COMPLETE
I have taken all indenting out as i thought this may be causing the error and the directories and files definitely exist. I have been on this for three days now and its wearing thin.
I had an if statement at the beginning to select devices on other handsets but i took this out in attempt to reduce errors (that's why i declare device instead of mounting).
here is the error:
ANDROID
HARDENING STARTED
mount: no such file or directory exist
, no such file or directorytcpdump
, no such file or directorysu
, no such file or directoryootanimation
, no such file or directoryumpstate
, no such file or directorying
, no such file or directorying6
ANDROID
HARDENING COMPLETED
NOTICE THE MERGING AFTER DIRECTORY THIS IS NOT A TYPO.
thanks Ryan
You edited this file on a Windows system and it has DOS-style end-of-lines (<cr><lf>). Convert it to use Unix-style end-of-line markers (<lf>) and it should work fine. Any decent programmer's editor will have the ability to do this for you, or you can do it using standard command line tools.
Incidentally, the shell doesn't care about indenting at all. This:
echo Hello
echo world.
Is the same as:
echo Hello
echo world.
Change the line ending to Unix style, will solve all your problem.
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)