1

I would like to copy the files, located on a remote machine, whose filenames match a prefix string, on my local machine.

I have tried to select only the files whose names start with either massif or calgrind using the following command:

scp my-machine:/home/user/a-folder/[massif,callgrind]* .

However, this expression allows to match the empty string plus any number of characters and therefore, matches all the filenames related to the directory.

What do I have to change to make it work correctly?

1
  • It seems that by using square brackets I was accepting any of the characters inside the square brackets and not the empty string as I first thought.
    – nico
    Commented Oct 25, 2018 at 5:14

2 Answers 2

1

It sounds like you want curly-brackets there:

scp my-machine:/home/user/a-folder/{massif,callgrind}* .

Otherwise you're matching on single characters, rather than the two complete strings.

bash does a number of different types of expansion & substitution; these are documented in the bash man page - looks for the EXPANSION section. Here, the [ type is covered under "Pathname Expansion" (it matches on pathnames) and { under "Brace Expansion" (it generates multiple arguments from the options provided, regardless of files present).

3
  • Aha! That is it. In fact it was accepting anything that would start with these letters plus the comma. Thank you!
    – nico
    Commented Oct 25, 2018 at 5:12
  • Also, do you happen to know how you call this construct/feature? It was hard to find this information in google. I always hit the if [[...]] or if[...] question from there.
    – nico
    Commented Oct 25, 2018 at 5:16
  • 1
    I've just added an edit with some references to documentation, hope that helps! Commented Oct 25, 2018 at 5:22
1

The files may be selected using two methods: the patterns may be specified consecutively or successively.

First method

This method requires to use a Bash extended pattern to specify several patterns together. The user must enable the extglob shell option using the shopt builtin (c.f. shopt builtin) because the Bash extended patterns are not enabled by default.

prompt% scp username@hostname:"/home/user/dirname/@(foo|bar)*" .

The Bash sub-pattern @(PATTERN-LIST) allows to specify a list of one or more patterns separated by |. It matches one of the given patterns. For example, @(foo|bar) matches foo or bar but does not match foobar, barfoo, foofoo, barbar.

The glob star matches any string of characters, including the empty string. Therefore, the pattern @(foo|bar)* matches all filenames that start with foo or bar (prefix (sub)string).

This method works when the remote shell is Bash and its extglob shell option is enabled. The user may enable this Bash option in its configuration file (e.g. ~/.bash_profile), on the remote machine.

Second method

This method executes the same command with different arguments, several times. It works using a POSIX compliant shell.

for prefix in foo bar
do
    scp username@hostname:"/home/user/dirname/${prefix}*" .
done

Brace expansion

This method is not robust because the resulting expression may specify filenames that do not exist.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .