In Bash,

echo a{b,c}d{e,f}


abde    abdf    acde    acdf

The output I'd like to see is

abde    acdf

In other words, given N parameters, I'd like Bash to use the ith parameter within each pair of braces to construct N strings.

  • N is the number of arguments between the curly braces. – Isaac Kleinman Oct 23 '13 at 1:09
  • Writing it as {bde,cdf} is not an option? Then you're probably left with a for loop and indexing arrays or something like that. – frostschutz Oct 23 '13 at 1:16
  • Actually, these are the two types of commands I was hoping to merge: git rm src/test/java/org/sonatype/mavenbook/AppTest.java and git rm src/main/java/org/sonatype/mavenbook/App.java – Isaac Kleinman Oct 23 '13 at 1:29
  • braces just control output. They aren't wildcards. As frostschutz suggested, what you are asking is a{bde,cdf} - two distinct endings that happen to have a middle character in common. If those two are files that exist, you could say a[bc]d[ef], but that predicates filename expansion and existence of the files (with no acde or abdf). You could as easily just echo abde acdf. Give us more info. Otherwise this is just "I wish it worked this way," which it definitely does not. – Paul Hodges Nov 29 '18 at 16:48

I would do this with arrays:

$ foo=( b c ); bar=( e f ); for i in {0..1}; do echo a${foo[$i]}d${bar[$i]}; done

I assume your actual use case is a bit more complex, so if you populate the arrays using another command and don't necessarily know their size, you can use:

foo=( b c ); bar=( e f ); for i in $(seq 0 $((${#foo[@]}-1))); do 
   echo a${foo[$i]}d${bar[$i]}; 

This is a silly answer, but here it is anyway:

$ echo a{b,c,d}e{f,g,h} | awk 'BEGIN {N=3;} { for (i=0; i<N; i++) { print $(i*N+i+1) } }'

$ echo a{b,c,d,1}e{f,g,h,2} | awk 'BEGIN {N=4;} { for (i=0; i<N; i++) { print $(i*N+i+1) } }'

$ echo a{b,c,d,1,A}e{f,g,h,2,Z} | awk 'BEGIN {N=5;} { for (i=0; i<N; i++) { print $(i*N+i+1) } }'

You can't change the way braces work.

If there is a string that doesn't appear in the text, say ,, you can apply successive string substitutions to an array:

a=(,b,e @c,f)
echo "${a[@]}"

A loop would be clearer though. If you want to stick the pieces together, you can use a separator that doesn't eappear in the strings, say , which would be special inside braces anyway.

a=(); IFS=,; set -f
for x in b,e c,f; do

Another approach is to define two parallel arrays.

version=(test main)
files=(AppTest.java App.java)
for ((i=0; i<${#files}; i++) rm "src/$version[i]/java/org/sonatype/mavenbook/files[i].java"

I think the easiest way to deal with this specific command would be to define a function.

rmapp () { rm "src/$1/java/org/sonatype/mavenbook/$2.java"; }
  • 1
    I think the function is the cleanest solution. All those loops look ugly (which is why I can't upvote this entire answer, alas). – Ian D. Allen Oct 24 '13 at 2:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.