Bash – Write bash function which operates on list of filenames

bashforfunctionscp

I want to define the function cpfromserver in bash so that when I run

$ cpfromserver xxx yyy zzz

the result is the same as if I had typed

$ scp user@remote.server:"/some/location/xxx/xxx.txt /some/location/xxx/xxx.pdf /some/location/yyy/yyy.txt /some/location/yyy/yyy.pdf /some/location/zzz/zzz.txt /some/location/zzz/zzz.pdf" /somewhere/else/

where it works for any number of arguments.

(That is, the function should copy filename.txt and filename.pdf from the directory /some/location/filename/ on the remote.server to the local directory /somewhere/else/ for every filename I specify as an argument to the function. And do it all in a single ssh connection.)

Currently, I have written a function that works for a single argument, and I just loop over it, but this establishes separate ssh connections for each argument, which is undesirable.

My difficulty is that I only know how to use function arguments individually by their position ($1, $2, etc.) — not how to manipulate the whole list.

[Note that I am writing this function as a convenience tool for my own use only, and so I would prioritize my own ease of understanding over handling pathological cases like filenames with quotation marks or linebreaks in them and whatnot. I know that the filenames I will be using this with are well-behaved.]

Best Answer

Try this way:

cpfromserver () {
    files=''
    for x in "$@"
    do
        files="$files /some/location/$x/$x.txt /some/location/$x/$x.pdf"
    done
    scp user@remote.server:"$files" /somewhere/else/
}

Important caveat from comments: "It's worth noting for posterity that this solution definitely won't work for complicated filenames. If a filename contains a space, or a newline, or quotes, this approach will definitely fail."