Copy multiple files securely using the scp command

botond published 2018/10/02, k - 01:23 time

Content

 

Introductory

These days, I needed a simple and practical solution to copy predefined files from my home computer to my server with a single command. I used to manually compile the files from different directories and then copy them one by one SSHthrough. Then I can easily access them from anywhere, eg from a mobile phone. Because these documents change often and I need to be able to open them remotely at any time, the manual copying method has become macerative. So I got bored of the banana and quickly put together a little shell script for it, with which I can even make these copies on time by running a single command. The script isn’t a big bang at all, I just thought I’d share it because of its practicality to see if it will come in handy if you’re looking for a similar solution.

So in this tutorial we will make a similar script, but first we will look at some examples of how to run the scp command.

 

 

The scp command

Whoever doesn't already know is scp (Secure Copy) command to copy files between two hosts over SSH. Thus, the scp program sends or receives the files specified in the parameter through an already encrypted channel.

Let's see some basic examples of sending and receiving. You can send files using the following syntax:

scp /file/eleresi/utvonala felhasznalo@szerver:~/cel/konyvtar

Here we specify the source file in the first parameter, in this case the file on the local machine, followed by the destination directory on the remote machine, which is here in the home directory of the specified user since it starts with ~ tilde. Of course, here too, you can specify absolute access (eg / home / user /), just because the target user usually copies to his / her own directory, so this is a shorter solution.

And now back:

scp felhasznalo@szerver:~/tavoli/forras/file/helye /helyi/cel/konyvtar

So there is no devil in this, just inverting the two parameters and copying it to the executor of the command.

It is even possible to copy file (s) from one remote server to another remote server:

scp felhasznalo@szerver1:~/tavoli/forras/file/helye felhasznalo@szerver2:~/tavoli/cel/konyvtar

When you run this command, shell prompts us for the remote machine's password for the specified user and copying starts.

Useful switches

It's also worth mentioning some of the switches in the scp command that can come in handy in certain situations:

Custom port setting

If the server to which you want to copy the files or from which you want to copy does not use the default port 22 for the SSH connection, but a different port number, use the (large) -P switch before specifying the source and destination files:

scp -P <egyedi portszám> <forrás fájl> <célfájl>

Keep timestamp of copied files

If it is important that the files retain their modification time during copying, use the (small) -p option:

scp -p <forrás fájl> <célfájl>

(There is no value assignment after the switch here.)

IPv4 / IPv6 Force

If the remote host does not have an IPv6 address, it is advisable to force the use of IPv4 with the -4 option:

scp -4 <forrás fájl> <célfájl>
This may be necessary because ISPs on newer endpoints already try to communicate over IPv6 (SCP, SSH, etc.) by default. For example, from another DIGI network, or from newer 4G mobile networks, you will no longer go up to SSH if you connect without a switch to a machine that only has an IPv4 address.
I was already running into this when my new mobile could not access the server via SSH on my 4G T-cell network and gave no error message on either side. And with the older DIGI net in Hungary, it connects seamlessly without the switch. It took about half a day for me to find this solution.

 

Similarly, the -6 switch can force IPv6 to be used if someone needs it.

Recursive copying

If you want to copy everything in a given directory, including its subdirectories, use the -r option before specifying the source and destination:

scp -r <forrás könyvtár> <cél könyvtár>

In this case, you must specify directories, the entire contents of which will be copied.

Copy multiple files at once

You can copy multiple files at the same time. There are several ways to do this:

Using a star character

The following example copies all files from the home directory of a user on a remote machine to the current directory:

scp felhasznalo@szerver:/home/felhasznalo/* .

It differs from the above recursive copy in that it does not copy any subdirectories in the directory, but only the files.

Of course, it also works the other way around:

scp * felhasznalo@szerver:/home/felhasznalo

This copies all files from the current directory of the local machine to the directory of the remote machine user.

Copy only the specified files

In the following example, we copy selected files from a directory on the remote machine:

scp felhasznalo@szerver:/tavoli/konyvtar/elerese/\{a,b,c\} .

So here you can specify specific filenames separated by commas separated by braces.

In this example, copy the specified files from the local machine (even from different directories) to the home directory of the destination machine user:

scp /tmp/a.txt /home/user/b.txt /etc/valami.conf felhasznalo@szervrer:~

 

Preparing scp for scripts

There is only one thing left before we can start using the scp command in shell scripts. Namely, to prevent the password from being requested, because when the scp command is run, our program crashes due to the password request. Because of this, we are unable to automate our copy jobs.

Fortunately, there is an excellent solution to this. In an earlier description I showed you how Access SSH using private and public keysto avoid typing your password. 

If we want to use any command that uses an SSH channel in scripts (ssh, scp, rsync, etc ...), then we need to perform this key generation method in order for our programs to run smoothly.

However, if you are over, you can move on to the next part.

 

 

The task

So now we know how to use the scp command, and we have eliminated the barrier to getting the password, so we can do the original job of creating a small copy script.

In this example, we will collect some files from different directories on the local machine and copy them to a remote machine directory.

There is already one of the above one-line examples, so you might think why we're screwing this up. However, in a script it is more convenient to solve everything, and to add things that the task requires. And last but not least, you will be able to run a single command afterwards.

So now let’s see a foundation from which to start. Let's say you have a few files from your local Linux server that need to be copied to another server from time to time for further processing, or just open them smoothly from elsewhere:

  • /var/log/ispconfig/httpd/weboldalam.hu/error.log
  • /home/pisti/backup/site1/2018-10-01_22_00.zip
  • /var/www/weboldalam.hu/exports/statistics.xml

I have just created direct longer file accesses to make it more uncomfortable to work on a single line command. Not to mention that from the middle file, say, an hour more is created, always named with the current time stamp. So it would be more macabre and unreasonable to cram it into a single command line. Instead, we'll make a few line scripts for him to fit in comfortably:

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
# Másoló szkript...
 
# Változók:
file1="/var/log/ispconfig/httpd/weboldalam.hu/error.log"
# file2="/home/pisti/backup/site1/2018-10-01_22_00.zip"
backupdir="/home/pisti/backup/site1/"
file2=${backupdir}$(ls -tr --group-directories-first ${backupdir}*.zip | tail -n 1)
file3="/var/www/weboldalam.hu/exports/statistics.xml"
 
# Másolás:
scp -P 12345 $file1 $file2 $file3 pisti@weboldalam.hu:~/Mentesek/

This way, you can easily access, change, etc. file names.

For example, in the case of the second file, I also left the commented fixed value assignment as a sample, and below it a parameterized with a reverse chronological order. ls command to retrieve the latest zip file in the directory, assuming there is no other zip file other than backups.

I put the backupdir in a variable because it was in two places, so there is no mixing when modifying. Also, I put the "--group-directories-first" option because it's not the default setting everywhere to put directories ahead, so the tail part can't even stumble upon a directory name by accident.

Finally, in the last line, copy to the remote server with the scp command.

Of course, if you want to expand the list of files you want to copy later, you can do it more elegantly using an array:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
# Másoló szkript...
 
# Változók:
backupdir="/home/pisti/backup/site1/"
filelist=(
    "/var/log/ispconfig/httpd/weboldalam.hu/error.log"
    ${backupdir}$(ls -tr --group-directories-first ${backupdir}*.zip | tail -n 1)   
    "/var/www/weboldalam.hu/exports/statistics.xml"
)
 
# Másolás:
scp -P 12345 ${filelist[@]} pisti@weboldalam.hu:~/Mentesek/

This way, you only need to add new rows with the file accesses to the elements in the array called "filelist", and they are already copied.

 

Conclusion

No matter how simple the task is, it is always worth considering whether to combine it all into a single command line, saying "it can be done anyway", or making it a handy script, with comments, variables, etc. that can be easily modified later. And finally you just have to run this one file or put it in cron, for example.

Also, here we have seen several uses of the scp command to securely copy files between our machines / servers, which can even be easily automated.