How to copy and edit files in Android shell?

AndroidLinuxShellAndroid NdkSh

Android 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.

  1. What to do if I have to copy some directories from read-only device recursively?
  2. 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.

  1. Launch Terminal and move to folder where adb is located. On Mac, usually at /Library/Android/sdk/platform-tools.
  2. Connect device now with developer mode on and check device status with command ./adb status. "./" is to be prefixed with "adb".
  3. 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.
  4. You may list out all folders using command ls -la.
  5. 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
  6. Now we can exit adb shell to access filesystem on our machine. Command: ./adb exit
  7. Now ./adb push [source location] [destination location]
    i.e. ./adb push ~/Documents/Videos/film.mp4 /sdcard/3233-3453/DCIM/Videos
  8. 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.

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
QuestionpsihodeliaView Question on Stackoverflow
Solution 1 - AndroidgnclmoraisView Answer on Stackoverflow
Solution 2 - AndroidViriatvsView Answer on Stackoverflow
Solution 3 - Androidp_lView Answer on Stackoverflow
Solution 4 - AndroidkuboView Answer on Stackoverflow
Solution 5 - AndroidjmbouffardView Answer on Stackoverflow
Solution 6 - Android18446744073709551615View Answer on Stackoverflow
Solution 7 - AndroidDiego Torres MilanoView Answer on Stackoverflow
Solution 8 - AndroidjrcView Answer on Stackoverflow
Solution 9 - AndroidHubbitusView Answer on Stackoverflow
Solution 10 - AndroidJoseView Answer on Stackoverflow
Solution 11 - AndroidbleaterView Answer on Stackoverflow