Bash: A Simple Script for Copying Files and Directories with SCP

This is a followup, of sorts, to an earlier post on file sharing in Xubuntu--which can be kind of a pain. I never looked seriously at SCP as a solution for file sharing because it's honestly tedious--true for both in-network and out-of-network sharing. With a little Bash scripting, though, SCP can be made a lot more practical. Here are a couple of short scripts that take the edge off.

Background

SCP is a command-line tool for passing files from one computer to another with SSH. That makes it a valuable tool no matter where those computers are: inside your home network, or off on some remote. The trouble I've always had with it, though, is remembering addresses: I can never remember the IP address of each and every device on my network, and some of the remotes I work with have really convoluted sub-domains. If it weren't for this, SCP would be a really great way to pass files from one place to another.

Conceptualizing a Script

What I really need, then, is a place to store all these difficult to remember IP's & domains--something like variables. Then, when I need to use SCP I can just pass a variable to SCP and not worry about remembering or mistyping some convoluted address. Simple enough.

Let's look at how SCP works. The basic syntax is essentially this:

$ SCP [/pathto/source/file.txt] [user@address:/pathto/destination/file.txt]
// or, for copying a directory, using the -r option
$ SCP -r [/pathto/source/folder] [user@address:/pathto/destination/folder]

I can put together an aliased script, then, with basically two variables: the first variable, "$1", will be a destination keyword (i.e., blog or pi); depending on the keyword, I can pass a destination path to the SCP command (i.e., user@example.com:~/pathto/destination/file.txt). The second variable, "$2", will be the path to the local file (i.e., [/pathto/source/file.txt]). The script, then, is really easy to put together: go ahead and create a file with your preferred editor and name it scpx.sh

The Script: SCP File Copy

Short and sweet--here's what it looks like:

#! /bin/bash 
# store destination paths in variables
blog="username@example.com:~/uploads"
pi="pi@192.168.X.X:/home/pi/Shared"
# parse filepath to get filename only and store in var
file="$(basename $2)"
# if $1 var equals "blog" format SCP to copy file ($2) to blog
[ "$1" == blog ] && scp "$2" "$blog"/"$file"
# if $1 var equals "pi" format SCP to copy file ($2) to raspberry pi
[ "$1" == pi ] && scp "$2" "$pi"/"$file"

I've aliased the script to run when I type scpx in the terminal--which means I would format my command like this: $ scpx [$1] [$2]--or, with actual values $ scpx blog /pathto/source/file.txt. If "$1" is equal to my keyword blog, then the blog username, address and destination file path all get passed to the SCP command. Note that the destination folder is fixed. Likewise, if "$1" is equal to pi, the script passes my raspberry pi credentials and a fixed path to the SCP command. The source file path, stored in "$2" is placed in the appropriate locations also within the SCP command, although it gets parsed with basename so that, if it's a long path, only the filename gets passed to the destination path. This means there's just one proviso on use of this script:

  1. I have fixed destination folders in which to copy files. In my blog server, for example, I keep a folder outside of the web-root specifically for SCP 'uploads'. I do this because the web-root is versioned with Git. I don't want stuff popping up in my git repository with SCP, and either way, the only thing I move to the blog outside of the repository are scripts and applications that need to run on the server. With my Raspberry Pi, I just like having a dedicated "Shared" folder so that I know what's coming in externally. If you want the flexibility to customize destination paths, this obviously isn't the script to do it. You could adapt the script to allow for custom destination paths, but... honestly, by then your keystroke savings start to diminish rather quickly: you might as well forgo the script and use SCP natively--maybe just place convoluted domains into Environment Variables (completely untested...). Ideally, to keep keystrokes to the minimum, you'd run this script from within the same directory as the file you're looking to move with SCP.

Here's the script in action, run from both in and outside the source file directory:

using a script to handle scp file copy
Here, sending the error.sh file to my Raspberry Pi from within the file directory; sending error2.sh to the Pi with an absolute path to the file. Either is an improvement over SCP's native syntax, but you can see why you'll get the best mileage when running the script from the same folder as the source file.

This covers files--which is great--but what about folders?

Another Script: SCP Folder Copy

In order to copy folders with SCP, you need to include the -r option in the command. You could potentially do this by using a third inline variable (i.e., "$3") with the script above. Personally, I opted for what I think is marginally less work: create another script, scpr.sh, and run it with a different alias $ scpr [$1] [$2]

#! /bin/bash 
# store destination paths in variables 
blog="username@example.com:~/uploads" 
pi="pi@192.168.X.X:/home/pi/Shared" 
# parse folder-path to get folder name only and store in var
folder="$(basename $2)"
# if $1 var equals "blog" format SCP to copy file ($2) to blog 
[ "$1" == blog ] && scp -r "$2" "$blog"/"$folder" 
# if $1 var equals "pi" format SCP to copy file ($2) to raspberry pi 
[ "$1" == pi ] && scp -r "$2" "$pi"/"$folder"

In the case of this script, of course, you'd want to run it from the parent directory of whatever directory it is you'd like to copy. Here's what this recursive script looks like in action:

running a recursive SCP command with a bash script
Sending the entire contents of my Scripts folder to my Raspberry Pi. Yes--I have Princess Bride jpegs in there!

That's about it. It's nothing too special, but it certainly takes some edge off of dealing with SCP. Hope some of you out there find it useful.