A very common task for a web developer is uploading a single file from a subdirectory on your development box to the same subdirectory on a remote server. Unfortunately, this always ends up being an annoying manual process involving switching directories on both servers, and wastes a large amount of time.

So, I've taken it upon myself to write a shell script to automate this for me, using scp for secure file copying. (Important Side Note:ftp is horribly insecure, use WinSCP instead)

The main problem to solve was that my Wordpress install on my development machine has a different base directory than the installation on my server. On my development machine it's /var/www, and on my server is something more like /var/www/howtogeek/docs/. I decided to just move those into variables at the beginning of the script, like this:

SSHSERVER=thegeek@hostname.com

RDIR=/var/www/howtogeek/docs

LDIR='\/var\/www'

Note that the local directory(LDIR) in the script has a \ before each / in the path. This is because we are going to pass this into a sed command later in the script, so we have to escape those values. I'm sure there's some other way around this, but I'm unaware of it.

Next, I set up automated ssh logins. To do this, you need to first run the ssh keygen utility like so:

ssh-keygen -t rsa

Then you need to copy the ~/.ssh/id_rsa.pub file to ~/.ssh/authorized_keys file on the remote server. If the ~/.ssh directory is already created on the remote server (might want to check), then you can run this command to copy the keys over:

cat ~/.ssh/id_rsa.pub | ssh user@hostname 'cat >> .ssh/authorized_keys'

Now we've got automated ssh logins, which will enable using the scp utility without a password. Now let's take a look at the scp command we'll use in the script:

scp $1 $SSHSERVER:$RDIR`pwd|sed "s/${LDIR}//"`/`echo $1|sed 's/.*\///'`

The $1 is the parameter you'll pass to the script for the filename you are trying to upload. $SSHSERVER and $RDIR are variables we'll set at the beginning of the script to set the user@hostname and the preceding remote path.

The first block that starts with pwd|sed takes the current directory path and strips off the preceding part of the path that doesn't match the remote server, but leaves the rest of the path. For instance, if you were in /var/www/wp-content/ when you ran the command, the sed block would strip off the /var/www based on our LDIR variable, but leave the /wp-content/ part of it.

The second block just makes sure to strip off the entire preceding path off the filename passed to the script so you just get the filename.

For example, if you named the script up.sh and ran it from your local /var/www/wp-content/plugins/ directory on a file:

up.sh myplugin.php

This would have been expanded by the shell as the following:

scp myplugin.php thegeek@hostname.com:/var/www/howtogeek/docs/wp-content/plugins/myplugin.php

Instead of trying to create your own script file based on the article, I've provided it for you to download. That way there won't be any issues with special characters not working... and yes, I used the script to upload itself =)

Download geek-uploader.sh

Just put it somewhere in your path, and name it whatever you want. I renamed mine to just "up", so I can just type "up filename.txt" to upload. Also remember to open it up and change the variables at the beginning of the script to match your environment.

This script should work on anything with a *nix shell and the scp utility. I'm using Ubuntu, but it should work on Solaris, OS X, or even Windows with Cygwin installed.