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