Bash – How to do multiple brace expansions without combinatorial explosion

bashbrace-expansioncommand line

I often use brace expansion on the command line, because it's handy.

Example

{foo,bar}

expands to:

foo bar

Multiple brace expansion also expand, e.g.:

{foo,bar}Q{foo,bar}

would expand to:

fooQfoo fooQbar barQfoo barQbar

This is expected behavior, where the brace expansions are used in order.

My Question

Now, I'd like the output of any brace expansion (or other short command line trick) to be:

fooQfoo barQbar

Note: I'm using bash 3.2

Best Answer

I couldn't figure out how to get this done using only curly braces. I don't see a way to achieve this either, so unless someone more clever than I can figure out a way I'd say it's not possible.

As an alternative

Sample Data

$ tree
.
|-- dir1
|   |-- file1
|   `-- file2
`-- dir2
    |-- file1
    `-- file2

Examples

$ seq 2 | xargs -i{} echo dir{}/file{}
dir1/file1
dir2/file2

This can be put into a command like this:

$ echo $(seq 2 | xargs -i{} echo dir{}/file{})
dir1/file1 dir2/file2

or this:

$ ls $(seq 2 | xargs -i{} echo dir{}/file{})
dir1/file1  dir2/file2

or this:

$ ls -l $(seq 2 | xargs -i{} echo dir{}/file{})
-rw-rw-r-- 1 saml saml 0 Sep  2 03:18 dir1/file1
-rw-rw-r-- 1 saml saml 0 Sep  2 03:31 dir2/file2

Why curly braces can't do this

If you look at your original example:

{foo,bar}Q{foo,bar}

The way this gets expanded is as follows:

fooQfoo fooQbar barQfoo barQbar

The mechanism that expanded this is called a Cartesian Product.

For example:

$ echo {A,B}{X,Y,Z}
AX AY AZ BX BY BZ

Or this:

$ echo {M,N}-{A,B}{X,Y,Z}
M-AX M-AY M-AZ M-BX M-BY M-BZ N-AX N-AY N-AZ N-BX N-BY N-BZ

There is no way to create a Cartesian Product that will result in:

fooQfoo barQbar

You're only option is to either resort to trickery such as this:

$ echo dir{1,2}/file{2,1}
dir1/file2 dir1/file1 dir2/file2 dir2/file1

And then put this into a Bash array:

$ a=(dir{1,2}/file{2,1})
$ echo ${a[@]:1:2}
dir1/file1 dir2/file2

The other option would be some "other method" such as the one I previously discussed above (using xargs) for example.

References

Related Question