I was running this single line for:

for i in `pwgen -yB -N 8 1`; do echo "$i"; done

Then the output is:


Some of those, like Descargas, Documentos, Escritorio belongs to my home folder (Which is in Spanish), where I run my cycle.

pwgen with argument -y produces at least one special nonalphanumerical character; -N param is for selecting the number of generated passwords (8) and the last 1 is for selecting the password lenght (1).

I am wondering which special character can echo $i be printing as my home content.

  • Maybe *? Can't think of anything other than that which would expand to contents – Munir Aug 5 '16 at 21:03

Don't do this:

for i in `pwgen -yB -N 8 1`

The result of command substitution is subjected to pathname expansion.

Do this instead:

pwgen -yB -N 8 1 | while IFS= read -r i; do printf '%s\n' "$i"; done


Observe that * appears in the output below, demonstrating that pathname expansion was not performed:

$ pwgen -yB -N 8 1 | while IFS= read -r i; do printf '%s\n' "$i"; done
  • I don't have pwgen so I can't see the original output, but I don't see what the while read loop accomplishes at all. It seems that it would pass through the input unmodified. What's the point? – Wildcard Aug 5 '16 at 23:09
  • 1
    @Wildcard The issue that the OP had was that the shell performed pathname expansion on * as it passed through his for loop. The answer here demonstrates that pathname expansion does not happen when using a while read loop. So, yes, the ability of the while loop to "pass through the input unmodified" is the point of the answer. – John1024 Aug 5 '16 at 23:20
  • Okay, but why not just use pwgen -yB -N 8 1 directly? Why use any kind of loop at all? – Wildcard Aug 5 '16 at 23:46
  • 2
    @Wildcard My interpretation was that the OP was doing some post-processing that failed because of the pathname expansion issue. He didn't want us to focus on the post-processing; he wanted us to solve the pathname expansion issue. This is what we recommend to OPs when we ask them to "create a Minimal, Complete, and Verifiable example". In this case, the removal of the post-processing was needed to meet the "minimal" criterion. – John1024 Aug 5 '16 at 23:52
  • 1
    @Wildcard I was just trying to perform the pwgen command into a cycle for creating passwords for a set of new users. This combination was for nothing special but testing the parameters (I tried a few different), and when I tried this it showed something different from a single special character: my home folder content. I just wondered why. Thank you for your answer @John1024. – Camilo Sampedro Aug 6 '16 at 20:44

You are using 'split' in for i in `command`.
But that also comes associated with "File Name Generation" (a.k.a. Pathname Expansion in bash) in which (unquoted) characters like *, ? and [ are expanded to "file names".

That could be turned off by: set -f.

set -f ; for i in `pwgen -yB -N 8 1`; do echo "$i"; done

To use an array might be a good idea:

$ set -f; arr=( $(pwgen -yB -N 4 1) ); printf '<%s>\n' "${arr[@]}"

Or perhaps:

$ set -f; arr=( $(pwgen -yB -N 5 18) ); printf '%s\n' "${arr[@]}"

Of course, you could use readarray to populate the array (no need for set -f):

$ readarray -t arr < <(pwgen -yB -N 8 1)

And then print all elements:

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

All in one line:

$ readarray -t arr < <(pwgen -yB -N 4 12); printf '%s\n' "${arr[@]}"
  • Thank you for your answer, I found useful to "turn off" the expansion and the array solution, I didn't know that could be done. – Camilo Sampedro Aug 6 '16 at 20:47

It's *:

for i in `echo '*'`; do echo "$i"; done

How to find it:

for i in `pwgen -yB -N 100 1 | tee /tmp/f1`; do echo "$i"; done >/tmp/f2
diff f1 f2

You might need to run it several times until you see a difference. Or increase N.

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.