When you ran:
scp -r ${server}:${server_dir}/$(ssh ${server} "ls -t ${server_dir} | head -5")
... the first (important) thing that happened was that your local shell began interpreting the command substitution here:
$(ssh ${server} "ls -t ${server_dir} | head -5")
The above command substitution mostly does what you think it does, except that it breaks as soon as there's a space or newline (or tab) in a filename. You might, for instance, have these 5 most recent files:
The ssh ... ls -t | head -5
will give you:
a
b
c
d
temp file
... but the command substitution strips newlines from the output, leaving you with this string being returned:
a b c d temp file
... which is now indistinguishable from the real, original, filenames.
You may never encounter such a filename, but it's safer to assume safety and never be bitten than the other way around.
As a result, I would suggest a direction in which you safely retrieve the filenames to the local system and then specifically retrieve them:
server=server-name-here ## replace with your values
server_dir=/tmp ## replace with your values
files=($(ssh "$server" "zsh -c 'print -N -- ${server_dir}/*(om.[1,5])'" 2>/dev/null ) )
for f in ${files[1,5]}
do
scp "${server}:${f}" logs/ios
done
The hardest part is retrieving the remote list of the five most recently-modified files. Here, I'm ssh'ing to the server and invoking zsh in order to use its extensive globbing mechanism to return:
- files from the ${server_dir}
- that are
o
rdered by m
odification time
- and are regular files (
.
)
- and just the first five:
[1,5]
The zsh built-in print
command is used here to return a null-separated -- and null-terminated — list of the resulting files. This null-containing string is passed back through ssh to zsh, who splits the string on nulls and assigns the contents to the files
array.
We then loop through that array, being careful to grab only the first five elements (as the sixth is a null value), then call scp
on each of those files in turn.
If you wanted to, you could carefully build up a string of remote filenames (${server}:${file1} ${server}:${file2} ...
) and call scp
just once. One possibility could be:
scp ${server}:${(qq)^files[1,5]} logs/ios
... as that instructs zsh to prepend the string (${server}, which is substituted with your real server name, followed by a colon) to the first five elements of the array. Any filenames from the array are quoted.
echo scp ... the rest of the command
; you'll see that you told scp to do something different than what you expected. Check out the first argument vs the 2nd and remaining arguments. – Jeff Schaller Sep 04 '18 at 17:45-r
with scp, when you say you're copying files? Are you expecting to catch directories? Your examples also look like gzipped tar files, not directories. – Jeff Schaller Sep 04 '18 at 17:59