How-To Geek

Shell Script to Upload a File to the Same Subdirectory on a Remote Server

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:

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/ 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/ | 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 and ran it from your local /var/www/wp-content/plugins/ directory on a file: myplugin.php

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

scp 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 =)


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.

Lowell Heddings, better known online as the How-To Geek, spends all his free time bringing you fresh geekery on a daily basis. You can follow him on if you'd like.

  • Published 06/10/07

Comments (5)

  1. Prithviraj

    I trying to connect secure server with u’r code but not able to suuceed
    I generate keys by ssh-key gen
    but after that not able login to ssh server it says
    ksh: .ssh/authorized-keys: cannot create
    Pseudo-terminal will not be allocated because stdin is not a terminal.
    The authenticity of host ‘xxxxxxxxxxxx’ can’t be established.

    can u please help me in this regard

  2. C@sPEr

    Hi The Geek,

    Do you have a similar script to login to remote server, download httpd logs to local server to be passed thru a stats generator (like awstats or webalizer) ?

  3. The Geek

    I’d recommend using rsync for that type of thing… one would assume the logs are always in a static directory.

    rsync -a* /local/folder/

    The -a means to use the archive switch, which will tag the items as archived once they’ve been downloaded.

  4. jenny

    It is really useful…

  5. Vamsii

    I use rsync ;)
    btw nice script.

More Articles You Might Like

Enter Your Email Here to Get Access for Free:

Go check your email!