Search code examples
bashescapingscpbash-function

Escaping parameter to bash function


First I'll describe the problem. I often copy files from my linux desktop to my android tablet. For reasons I'd rather not go into, the easiest way I found to do this is by running sshDroid (a ssh server) on my tablet, and using scp from the shell to copy files over. The scp command takes the following form:

scp -P 2222 ./some\ document\:\ with\ subtitle\ -\ author.txt \
            root@197.157.0.211:/sdcard/uploads

The only thing that changes in this expression is the name of the file, and that is quite easily attained via tab-completion. Not even the ip address changes. Since I upload files quite often, I would very much like to not type the same characters over and over again. To this end I thought I would write a shell function and append it to .bashrc. The function I wrote is as follows:

upload(){ scp -P 2222 $@ root@192.168.0.151:/sdcard/uploads; }

it's usage is supposed to be:

upload ./some\ document\:\ with\ subtitle\ -\ author.txt

but when I try it I get the following output:

SSHDroid
Use 'root' as username
Default password is 'admin'
root@192.168.0.151's password: 
./some: No such file or directory
ssh: Could not resolve hostname document: Name or service not known
with: No such file or directory
subtitle: No such file or directory
-: No such file or directory
author.txt: No such file or directory

It looks like bash is automatically unescaping the filename before it passes it to the function, and the scp command treats it as multiple filenames due to the spaces in the name.

My question is: How do I preserve the backslashes in the parameter, or failing that how do I reescape it within the function? After fiddling with this for a while I'm sorely tempted to write a simple python script and drop it into /usr/local/bin. Is there some other bash-native solution that I'm missing?


Solution

  • Quotes!

    Unquoted, $@ behaves identically to $*; if you want to preserve original tokenization, you need to use "$@" instead. Thus:

    upload() { scp -P 2222 "$@" root@192.168.0.151:/sdcard/uploads; }