How to copy and edit files in Android shell?
AndroidLinuxShellAndroid NdkShAndroid Problem Overview
The Android shell does not have the cp command. Android shell also has no sed or grep or vi. I have no adb daemon available. There is mv command but it rejects to work if source is on a read-only device.
- What to do if I have to copy some directories from read-only device recursively?
- How to change a line in a text file (e.g. "PATH=/cache" to be "PATH=/mnt/asec") ?
Android Solutions
Solution 1 - Android
To copy dirs, it seems you can use adb pull <remote> <local>
if you want to copy file/dir from device, and adb push <local> <remote>
to copy file/dir to device. Alternatively, just to copy a file, you can use a simple trick: cat source_file > dest_file
. Note that this does not work for user-inaccessible paths.
To edit files, I have not found a simple solution, just some possible workarounds. Try this, it seems you can (after the setup) use it to edit files like busybox vi <filename>
. Nano seems to be possible to use too.
Solution 2 - Android
You can do it without root permissions:
cat srcfile > /mnt/sdcard/dstfile
Solution 3 - Android
The most common answer to that is simple: Bundle few apps (busybox?) with your APK (assuming you want to use it within an application). As far as I know, the /data partition is not mounted noexec, and even if you don't want to deploy a fully-fledged APK, you could modify ConnectBot sources to build an APK with a set of command line tools included.
For command line tools, I recommend using crosstool-ng and building a set of statically-linked tools (linked against uClibc). They might be big, but they'll definitely work.
Solution 4 - Android
You can use cat > filename
to use standart input to write to the file. At the end you have to put EOF CTRL+D
.
Solution 5 - Android
Also if the goal is only to access the files on the phone. There is a File Explorer that is accessible from the Eclipse DDMS perspective. It lets you copy file from and to the device. So you can always get the file, modify it and put it back on the device. Of course it enables to access only the files that are not read protected.
If you don't see the File Explorer, from the DDMS perspective, go in "Window" -> "Show View" -> "File Explorer".
Solution 6 - Android
Since the permission policy on my device is a bit paranoid (cannot adb pull
application data), I wrote a script to copy files recursively.
Note: this recursive file/folder copy script is intended for Android!
copy-r:
#! /system/bin/sh
src="$1"
dst="$2"
dir0=`pwd`
myfind() {
local fpath=$1
if [ -e "$fpath" ]
then
echo $fpath
if [ -d "$fpath" ]
then
for fn in $fpath/*
do
myfind $fn
done
fi
else
: echo "$fpath not found"
fi
}
if [ ! -z "$dst" ]
then
if [ -d "$src" ]
then
echo 'the source is a directory'
mkdir -p $dst
if [[ "$dst" = /* ]]
then
: # Absolute path
else
# Relative path
dst=`pwd`/$dst
fi
cd $src
echo "COPYING files and directories from `pwd`"
for fn in $(myfind .)
do
if [ -d $fn ]
then
echo "DIR $dst/$fn"
mkdir -p $dst/$fn
else
echo "FILE $dst/$fn"
cat $fn >$dst/$fn
fi
done
echo "DONE"
cd $dir0
elif [ -f "$src" ]
then
echo 'the source is a file'
srcn="${src##*/}"
if [ -z "$srcn" ]
then
srcn="$src"
fi
if [[ "$dst" = */ ]]
then
mkdir -p $dst
echo "copying $src" '->' "$dst/$srcn"
cat $src >$dst/$srcn
elif [ -d "$dst" ]
then
echo "copying $src" '->' "$dst/$srcn"
cat $src >$dst/$srcn
else
dstdir=${dst%/*}
if [ ! -z "$dstdir" ]
then
mkdir -p $dstdir
fi
echo "copying $src" '->' "$dst"
cat $src >$dst
fi
else
echo "$src is neither a file nor a directory"
fi
else
echo "Use: copy-r src-dir dst-dir"
echo "Use: copy-r src-file existing-dst-dir"
echo "Use: copy-r src-file dst-dir/"
echo "Use: copy-r src-file dst-file"
fi
Here I provide the source of a lightweight find
for Android because on some devices this utility is missing. Instead of myfind
one can use find
, if it is defined on the device.
Installation:
$ adb push copy-r /sdcard/
Running within adb shell
(rooted):
# . /sdcard/copy-r files/ /sdcard/files3
or
# source /sdcard/copy-r files/ /sdcard/files3
(The hash #
above is the su
prompt, while .
is the command that causes the shell to run the specified file, almost the same as source
).
After copying, I can adb pull
the files from the sd-card.
Writing files to the app directory was trickier, I tried to set r/w permissions on files
and its subdirectories, it did not work (well, it allowed me to read, but not write, which is strange), so I had to do:
String[] cmdline = { "sh", "-c", "source /sdcard/copy-r /sdcard/files4 /data/data/com.example.myapp/files" };
try {
Runtime.getRuntime().exec(cmdline);
} catch (IOException e) {
e.printStackTrace();
}
in the application's onCreate().
PS just in case someone needs the code to unprotect application's directories to enable adb shell
access on a non-rooted phone,
setRW(appContext.getFilesDir().getParentFile());
public static void setRW(File... files) {
for (File file : files) {
if (file.isDirectory()) {
setRW(file.listFiles()); // Calls same method again.
} else {
}
file.setReadable(true, false);
file.setWritable(true, false);
}
}
although for some unknown reason I could read but not write.
Solution 7 - Android
If you have root access install busybox (google for instructions).
Solution 8 - Android
Android supports the dd command.
dd if=/path/file of=/path/file
Solution 9 - Android
I could suggest just install Terminal-ide on you device which available in play market. Its free, does not require root and provide convenient *nix environment like cp, find, du, mc and many other utilities which installed in binary form by one button tap.
Solution 10 - Android
I tried following on mac.
- Launch Terminal and move to folder where adb is located. On Mac, usually at
/Library/Android/sdk/platform-tools
. - Connect device now with developer mode on and check device status with command
./adb status
."./"
is to be prefixed with "adb". - Now we may need know destination folder location in our device. You can check this with
adb shell
. Use command./adb shell
to enter an adb shell. Now we have access to device's folder using shell. - You may list out all folders using command
ls -la
. - Usually we find a folder
/sdcard
within our device.(You can choose any folder here.) Suppose my destination is/sdcard/3233-3453/DCIM/Videos
and source is~/Documents/Videos/film.mp4
- Now we can exit adb shell to access filesystem on our machine. Command:
./adb exit
- Now
./adb push [source location] [destination location]
i.e../adb push ~/Documents/Videos/film.mp4 /sdcard/3233-3453/DCIM/Videos
- Voila.
Solution 11 - Android
If you just want to append to a file, e.g. to add some lines to a configuration file, inbuilt shell commands are enough:
adb shell
cat >> /path/to/file <<EOF
some text to append
a second line of text to append
EOF
exit
In the above, replace /path/to/file
with the file you want to edit. You'll need to have write permission on the file, which implies root access if you're editing a system file. Secondly, replace some text to append
and a second line of text to append
with the lines you want to add.