5

In bash, I've written a function that loops over files in a directory with multiple extensions using wildcards, and copies only these specific files if they exist. A snippet of the code looks like this:

set -e

pushd ../../../../$3/code/project/common/ > /dev/null
mkdir -p ../$2
shopt -s nullglob

for file in *.gyp; do   cp $file ../$2/; done
for file in *.gypi; do  cp $file ../$2/; done
for file in *.sh; do    cp $file ../$2/; done
for file in *.patch; do cp $file ../$2/; done

popd > /dev/null

I'd prefer instead to write one for file in x statement, so that I don't have to copy and paste this line for each extension I want to copy.

How can I rewrite the four for statements as one for statement? I would like to keep the *.ext wildcard format somewhere in there if possible.

tjgrant
  • 438
  • 4
  • 18
  • 1
    See: [Matching files with various extensions using for loop](https://stackoverflow.com/q/6223817/3776858) – Cyrus Feb 17 '19 at 15:01
  • [Shellcheck](https://www.shellcheck.net/) identifies several instances of missing quotes in the code. – pjh Feb 18 '19 at 19:42

2 Answers2

6

You should just be able to do

for file in *.gyp *.gypi *.sh *.patch; do   cp $file ../$2/; done
Joe
  • 41,484
  • 20
  • 104
  • 125
  • Well I feel silly… I don't think I would have ever thought of that, or that this would work. Thanks for your answer! – tjgrant Feb 17 '19 at 15:05
  • Based off of your response and Cyrus (from above), I've rewritten it as this, which is a bit more compact: `for file in *.{gyp,gypi,sh,patch}; do cp $file ../$2/; done`, and that's what I'll be going with. Thanks again! – tjgrant Feb 17 '19 at 15:08
  • 1
    This does not work if there are no matches, e.g. if there are no .sh files the value for $file will be '*.sh' – Konstantin Glukhov May 14 '22 at 03:26
4

Brace Expansion and a single cp command:

cp -t ../"$2" *.{gyp,gypi,sh,patch}

Always quote your variables, unless you know exactly what side-effects you want.

glenn jackman
  • 238,783
  • 38
  • 220
  • 352