6

I want to create a simple bash-script that checks whether a directory contains all the files whose names contain numbers from 1 to N.

# Creating some files for testing
$ cd /tmp/
$ mkdir test
$ touch test/a01x.dat
$ touch test/b02y.dat

# Display dir contents
$ ls test/*{01,02}*
test/a01x.dat  test/b02y.dat

But using seq command to generate numbers results in the following:

$ ls test/*{$(seq -s , -f "%02g" 1 2)}*
ls: cannot access 'test/*{01,02}*': No such file or directory

I understand that running the command by surrounding the path with single quotation marks must lead to the error because the wildcards don't expand

$ ls 'test/*{01,02}*'

But I didn't use them. What is the problem?

ilkkachu
  • 133,243
  • 15
  • 236
  • 397
ka3ak
  • 1,235
  • 4
  • 18
  • 30
  • "check whether a directory contains all the files" - do you want to do something if a file doesn't exist with that number in it? Or do you just want to show files that contain one of those numbers as part of the file name (your `ls test/*{01,02}*` seems to indicate so...) ? Also, what format will the numbers be in? If N=100 will you use 001 or 1 or ?? to start? – ivanivan Oct 20 '18 at 14:49
  • @ivanivan I've renamed the question – ka3ak Oct 20 '18 at 15:04
  • The `cannot access` error message from `ls` always shows the name in question surrounded with quotes, that has nothing to do with your problem. It might depend on the version of `ls`, though. Try something like `ls foo "foo "` – ilkkachu Oct 20 '18 at 17:48

1 Answers1

11

The problem is that the shell will do brace expansion (which processes {...,...}) before it does command substitution (the $(...) part.) So after your seq is expanded, the shell will not re-evaluate the {01,02} and will leave it as a literal.

You need to add an eval to have it re-evaluate the expression after the command substitution is performed:

$ eval "ls test/*{$(seq -s , -f "%02g" 1 2)}*"

In this case, the command substitution will be performed first, resulting in a string ls test/*{01,02}* and the eval will ask the shell to interpret this as a command, which will then perform the brace and glob expansion, resulting in the list of files you're expecting.

filbranden
  • 21,113
  • 3
  • 58
  • 84