8

I used the following command to create a list of URLs that I want to test:

echo -e localhost:8080/reports/{promos,promo-updates,scandown}/{130,139,142}{,-unburdened,-burdened}{,.pdf,.xls,.xlsx,.csv,.preload}"\n" >> urls.txt

Unfortunately the URLs appended to urls.txt each had a space before them (except for the first, of course). I understand why that happened, and I realize I could just strip it off by piping throug a sed expression, but I'd like to know if there's a way to suppress it instead. (It may seem silly and pedantic, but it's no different than the preference so many people feel for not "abusing cats".)

I tried double-quoting to suppress word-splitting, but that suppressed the brace expansion too, so that was a no-go.

I tried changing IFS to an empty string, but it didn't work either:

IFS='' echo -e localhost:8080/reports/{promos,promo-updates,scandown}/{130,139,142}{,-unburdened,-burdened}{,.pdf,.xls,.xlsx,.csv,.preload}"\n" >> urls.txt

Nor did changing it to a newline:

IFS='\n' echo -e localhost:8080/reports/{promos,promo-updates,scandown}/{130,139,142}{,-unburdened,-burdened}{,.pdf,.xls,.xlsx,.csv,.preload}"\n" >> urls.txt
4
  • Are you using bash or zsh?
    – Braiam
    Jul 24, 2014 at 16:17
  • at the moment I'm using bash (I'm at work) but on my own laptop I use zsh. I was expecting brace expansion to work identically in both, but perhaps that's not the case.
    – iconoclast
    Jul 24, 2014 at 16:48
  • In that case Gnouc answer will be the most compatible with different shells.
    – Braiam
    Jul 24, 2014 at 16:54
  • Wouldn't richard's answer be equally compatible? (It also has the advantage of being simpler, therefore I don't have to stop and think about the fiddly bits the next time I want to use it.) On the other hand, Gnouc's answer is also excellent. And I think I learned the most from glenn jackson's answer. Leiaz's answer seems simplest and most elegant, but of course is zsh-only.
    – iconoclast
    Jul 24, 2014 at 17:11

4 Answers 4

16

Use printf builtin:

$ printf %s\\n localhost:8080/reports/{promos,promo-updates,scandown}/{130,139,142}{,-unburdened,-burdened}{,.pdf,.xls,.xlsx,.csv,.preload}
localhost:8080/reports/promos/130
localhost:8080/reports/promos/130.pdf
localhost:8080/reports/promos/130.xls
localhost:8080/reports/promos/130.xlsx
localhost:8080/reports/promos/130.csv
localhost:8080/reports/promos/130.preload
localhost:8080/reports/promos/130-unburdened
localhost:8080/reports/promos/130-unburdened.pdf
localhost:8080/reports/promos/130-unburdened.xls
localhost:8080/reports/promos/130-unburdened.xlsx
localhost:8080/reports/promos/130-unburdened.csv
localhost:8080/reports/promos/130-unburdened.preload
....
9

You could store the brace expansion in an array, then output it in the manner of your choosing:

urls=( localhost:8080/reports/{promos,promo-updates,scandown}/{130,139,142}{,-unburdened,-burdened}{,.pdf,.xls,.xlsx,.csv,.preload} )

Then

printf "%s\n" "${urls[@]}"

or

(IFS=$'\n'; echo "${urls[*]}")

The echo example looks weird because:

  1. it's run in a subshell (the parentheses) so I don't alter my current value of IFS.
  2. IFS needs to be defined in a separate command:
    • This doesn't work: IFS=$'\n' echo "${urls[*]}" because the variable gets expanded before the new env variable takes effect
    • IFS needs to be set before you start expanding variables.

Also, note the subtle difference in the dereferencing array index used:

  • [@] in the printf example to expand the array into individual words
  • [*] in the echo example to expand the array into a single word, with elements separated by the first char of IFS
1
  • It's a hard call, but I'm choosing this answer because (1) it seems (AFAIK) to be the closest to the stated goal of suppressing rather than merely removing the spaces, and (2) I learned the most from it (a stated goal of my question).
    – iconoclast
    Jul 24, 2014 at 21:57
6

This is tagged zsh, so I suggest the zsh builtin print :

print -l localhost:8080/reports/{promos,promo-updates,scandown}/{130,139,142}{,-unburdened,-burdened}{,.pdf,.xls,.xlsx,.csv,.preload}

-l prints arguments on separate lines.

1
  • +1 Thanks--good to know! I'll use that when I'm on zsh. I tagged it that simply because I use both and both support brace expansion. (I don't know if any others do, but I find ksh terribly confusing, so I stay away.)
    – iconoclast
    Jul 24, 2014 at 15:07
3

The problem is the brace expansion is adding the space, and echo is adding the newline. So using single responsibility principle, handle the newline separately.

echo -e localhost:8080/reports/{promos,promo-updates,scandown}/{130,139,142}{,-unburdened,-burdened}{,.pdf,.xls,.xlsx,.csv,.preload} | tr " " "\n"
3
  • I think this is the simplest and most practical approach
    – iconoclast
    Jul 24, 2014 at 21:55
  • No, brace expansion is not adding the space, it's creating several arguments to echo. That's echo that prints its arguments separated by spaces. Jul 30, 2014 at 6:39
  • I guess the problem occurs because echo separates arguments by spaces and the newline is inserted additionally before each space instead of replacing the space (which would be more sensible). From memory, xargs has a known issue very similar to this one (especially with the -0 option) Nov 8, 2014 at 1:07

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.