1

I would like to copy a series of similar files from the current directory to the target directory, the files under the current directory are:

prod07_sim0500-W31-0.2_velocity-models-2D_t80_f0001_ux.hst
prod07_sim0500-W31-0.2_velocity-models-2D_t80_f0001_uz.hst
prod07_sim0500-W31-0.2_velocity-models-2D_t80_f0002_ux.hst
prod07_sim0500-W31-0.2_velocity-models-2D_t80_f0002_uz.hst
prod07_sim0500-W31-0.2_velocity-models-2D_t80_f0003_ux.hst
prod07_sim0500-W31-0.2_velocity-models-2D_t80_f0003_uz.hst

Where sim is from sim0001 to sim0500 and f is from f0001 to f0009. I only need f0002, f0005 and f0008. I write the following code:

target_dir="projects/data"

for i in {0001..0500}; do
    for s in f000{2,5,8}; do
        files="[*]$i[*]$s[*]"
        cp $files target_dir
    done
done

I am very new to Shell, and wondering how to write the $files="[*]$i[*]$s[*]"$, so that it could match only the f0002, f0005 and f0008. The reason why I also use for i in {0001..0500}; do is that the files are too large and I would like to make sure I could access some completed ones (for example, including all sim0001) in the beginning.

Edit: changed for s in f0002 f0005 f0008; do to f000{2,5,8}.

l0b0
  • 55,365
  • 30
  • 138
  • 223
Panfeng Li
  • 3,321
  • 3
  • 26
  • 34
  • What about `cp *sim0[0-5][0-9][0-9]-*_f000[258]_* /target/` ? Fill in globs as required, of course... Might barf if you have more files than [ARG_MAX](https://stackoverflow.com/a/19355351/1072112), but I don't see the need for loops. (Yes, I know this also matches sim0000.. If that's a concern, split it into two commands. Still less typing and headaches than nested loops.) – ghoti Nov 21 '18 at 02:31

1 Answers1

3

What you need is globbing and a bit different quoting:

cp *"$i"*"$s"* "$target_dir"

Not storing this in a variable is intentional - it's faster and it's safe. If you end up with such a large list of files that you start running into system limits you'll have to look into xargs.

l0b0
  • 55,365
  • 30
  • 138
  • 223
  • Maybe emphasize that both quoting the wildcard and embedding it in square brackets individually turns the wildcard into a literal `*`. You have to remove both the quotes and the square brackets before you get an actual wildcard. – tripleee Nov 21 '18 at 05:26
  • Both of those (and more) should be very well explained by the linked articles. – l0b0 Nov 21 '18 at 10:02