I have a shell function to help me scp files to and from servers. Both servers are running bash on Ubuntu 22.04. Let’s call the server comp2
and pretend its IP address for is 192.168.1.2
On my server in the /home/.bashrc
file I have this as my alias:
tocomp2() {
scp "$1" [email protected]:"$2"
}
fromcomp2() {
scp [email protected]:"$1" "$2"
}
Let’s pretend I have three files foo1
foo2
and foo3
in my working directory, and three files bar
bar2
bar3
in the home directory of comp2
. Odd things happen when I use the wildcard to move these files.
tocomp2 foo* /home/
only transfers foo1
tocomp2 foo* /home/
doesn’t find any files.
fromcomp2 bar* ./
or fromcomp2 bar* ./
transfers all three bar
files
EDIT: Better question to ask is, how can I make tocomp2
act like fromcomp2
where the wildcard actually selects all foo
files?
2
Answers
Actually
tocomp2 foo* /home/
expands totocomp2 foo1 foo2 foo3 /home/
which copiesfoo1
but renames it tofoo2
, and ignores the remaining arguments.Writing functions where the first argument is special is simpler; with
you could get what you want with
tocomp3 . foo*
where.
is the destination directory at the target.foo*
expands to as many arguments as there are matching files (or the one literal argumentfoo*
if no matches are found). If you have the filesfoo1
foo2
andfoo3
in your directory then it expands to three arguments sotocomp2 foo* /home/
has four arguments in total and you are only referencing the first two in your code.foo*
passes the literal argumentfoo*
, and the quotes in"$1"
disable the pathname expansion so it remains a literal argument.A common fix is to put the known arguments in front and the variable arguments at the end of the call, then you can use
"$@"
to reference them all without knowing the exact count.If you don’t like the reversed syntax then you can pull the last argument off the list and build a new array with everything except it: