5

I am trying to match and loop through files with extensions .txt .h .py. in specific folder ${arg}. Here is what I did

for file in ${arg}/*.{txt, h, py}; do
  ...

done

However I got no such file for all extensions even though I have such files.

 line 24: dir1/*.{txt,: No such file or directory
 line 24: h,: No such file or directory
 line 24: py}: No such file or directory

How can I loop though the files with specified extensions using for ?

Mark
  • 8,038
  • 15
  • 55
  • 78

3 Answers3

13

Lose the spaces; bash cares.

for file in "${arg}"/*.{txt,h,py}; do
Ignacio Vazquez-Abrams
  • 740,318
  • 145
  • 1,296
  • 1,325
10

I would like to suggest 2 improvements to the proposed solution:

A. The for file in "$arg"/.{txt,h,py} will also produce "$arg"/.txt if there are no files with txt extention and that creates errors with scripts:

$ echo *.{txt,h,py}
*.txt *.h doSomething.py

To avoid that, just before the for loop, set the nullglob to remove null globs from from the list:

$ shopt -s nullglob # Sets nullglob
$ echo *.{txt,h,py}
doSomething.py
$ shopt -u nullglob # Unsets nullglob

B. If you also want to search *.txt or *.TXT or even *.TxT (i.e. ignore case), then you also need to set the nocaseglob:

$ shopt -s nullglob # Sets nullglob
$ shopt -s nocaseglob # Sets nocaseglob
$ echo *.{txt,h,py}
myFile.TxT doSomething.py
$ shopt -u nocaseglob # Unsets nocaseglob
$ shopt -u nullglob # Unsets nullglob
Nick De Greek
  • 1,744
  • 1
  • 17
  • 18
5

As Ignacio already told you should delete the spaces. And if you want do this recursively for the subdirectories too use the double ** globbing:

for file in ${arg}/**/*.{txt,h,py}
do
    ....
done

ps: works only in bash4

jm666
  • 58,683
  • 17
  • 101
  • 180