0

Can somebody explain please how this work ? I just don't understand how builtin echo command interacts with directory listing..

bash-5.2$ ls
2   file000 file003 file006 file009 file012 file015 file018 file021 file024 file027 h
5   file001 file004 file007 file010 file013 file016 file019 file022 file025 file028 ola
8   file002 file005 file008 file011 file014 file017 file020 file023 file026 file029 q
bash-5.2$ echo [0-9a-z]
2 5 8 h q

Thanks.

1 Answers1

5

This has nothing to do with echo, echo just prints the arguments it receives separated by spaces and terminated by a newline (after some potential option processing and backslash escape handling).

What you're seeing here is the effect of shell globbing, aka filename generation aka pathname expansion, whereby when, in list contexts, if some words contain some unquoted globbing pattern operators which include *, ? and (except in fish), [...] (and possibly more depending on the shell), the word is expanded by the shell to the list of matching files in the directory tree.

That happens regardless of the command, whether it's echo, rm, firefox...

You'll probably have seen it in things like:

rm -- *.txt

There, it's the * that triggers the behaviour.

In:

echo [0-9a-z]

It's [...] that triggers it. As a pattern, [0-9a-z] matches on any one character that is either between 0 and 9 or between a and z¹, so as a globbing operator, that [0-9a-z] word will expand to all the single-character file names in the current working directory that match that pattern.

And rm -- [0-9a-z] will remove them, vi -- [0-9a-z] will edit them, etc.

Important note: the command, whether that's rm, echo, vi... only sees the result of the expansion (as separate arguments), not the pattern. In particular, if the first² filename in that expansion starts with -³, it may be taken as an option with possibly disastrous effects, so, like in cmd -- $files, it's critical not to forget that --⁴.


¹ which includes characters such as your 2, 5, 8, h, q but also often (and often overlooked) things like ², DŽ, , and thousands more and even sometimes sequences of more than one character which happen to be some collating element sorting in that range in the locale. If you want to only match on the 10 ASCII decimal digits and the 26 lower case ASCII letters of the English alphabet, either use zsh where the [x-y] ranges are based on code points or change [0-9a-z] to [0123456789abcdefghijklmnopqrstuvwxyz].

² or following words for those utilities that accept options after non-option arguments such as in many GNU utilities (even though that's not allowed by POSIX).

³ or + with some utilities such as sh, sort, set.

⁴ the fact that echo doesn't accept -- as the option delimiter (except for the echo builtin of fish, zsh's accepts -) is one of the many reasons it can't be used reliably.