Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Meta characters are expanded differently

23 views
Skip to first unread message

parmenides

unread,
Jan 29, 2015, 4:37:07 AM1/29/15
to
I wonder why the following two commands get different results.

[root@centos6 tmp]# ls
note01 note02 note03 note04
[root@centos6 tmp]# echo * book
note01 note02 note03 note04 book
[root@centos6 tmp]# echo *book
*book
[root@centos6 tmp]#

I think the meta character '*' should be expanded equally, regardless of
wheter or not there is a space following the '*'.

Stachu 'Dozzie' K.

unread,
Jan 29, 2015, 4:46:54 AM1/29/15
to
Why should it? There's no file called "<something>book". If anything,
whole command should fail with an error, like zsh does with NOMATCH
option.

--
Secunia non olet.
Stanislaw Klekot

Janis Papanagnou

unread,
Jan 29, 2015, 4:49:44 AM1/29/15
to
No. The first '*' expands to "everything" (sort of; no dot-files) followed
by a constant string "book". The second one tries to match a word ending in
"book"; if there is none then the pattern is taken (and printed) literally.

BTW, you really shouldn't use the root account to test things, specifically
if you are uncertain what your shell commands actually do.

Janis

frank.w...@gmail.com

unread,
Jan 29, 2015, 5:23:05 AM1/29/15
to
From parmenides:
>I think the meta character '*' should be expanded equally, regardless of
>wheter or not there is a space following the '*'.

It does expand equally here, but the space is a
delimiter, it is not one of the characters in the
pattern.

Frank

parmenides

unread,
Jan 29, 2015, 7:59:30 AM1/29/15
to
在 2015/1/29 17:49, Janis Papanagnou 写道:
> On 29.01.2015 10:37, parmenides wrote:
>> I wonder why the following two commands get different results.
>>
>> [root@centos6 tmp]# ls
>> note01 note02 note03 note04
>> [root@centos6 tmp]# echo * book
>> note01 note02 note03 note04 book
>> [root@centos6 tmp]# echo *book
>> *book
>> [root@centos6 tmp]#
>>
>> I think the meta character '*' should be expanded equally, regardless of
>> wheter or not there is a space following the '*'.
>
> No. The first '*' expands to "everything" (sort of; no dot-files) followed
> by a constant string "book". The second one tries to match a word ending in
> "book"; if there is none then the pattern is taken (and printed) literally.
>
Ok, I think I get it. I has been stunck in an idea that the '*' should
be expended individually.

> BTW, you really shouldn't use the root account to test things, specifically
> if you are uncertain what your shell commands actually do.
Thanks for your advise.

>
> Janis
>

Kaz Kylheku

unread,
Jan 29, 2015, 10:01:58 AM1/29/15
to
On 2015-01-29, parmenides <mobile.p...@gmail.com> wrote:
> I think the meta character '*' should be expanded equally, regardless of
> wheter or not there is a space following the '*'.

So for instance, we should have this?

$ ls
file.c file.o

$ echo *
file.c file.o

$ echo foo*bar
foofile.c file.obar

If not, why should we have this:

$ echo foo*
foofile.c file.o

or this:

$ echo *foo
file.c file.obar

How it works is that foo* is a single argument, and the syntax means "match
names which begin with foo". Whereas foo * is two arguments: the arguments
foo, and an argument which means "match any name (that doesn't begin
with a dot)".

Thomas 'PointedEars' Lahn

unread,
Jan 31, 2015, 5:20:16 PM1/31/15
to
JFTR: If you need that, you can write

ls *' book'

which would list all files (without “shopt -s dotglob”, only those whose
name is not starting with a dot) whose name ends in “ book”. You can also
use double-quotes:

$ ls *" book"
My book

This has the advantage of easy use of apostrophes –

$ ls *"'"*"books"
Frank's books
Thomas' books
parmenides' books

– and the possibility of safe parameter expansion:

$ suffix='favorite books'
$ ls *"'"*"$suffix"
Frank's favorite books
Thomas' favorite books
parmenides' favorite books

The disadvantage is that you may need to write more escape sequences then,
for example if a filename contains a backslash. But you can switch back to
single quotes for that part:

$ suffix='favorite books'
$ ls *"'"*"$suffix"' on \\shares\for-all'
Frank's favorite books on \\shares\for-all
Thomas' favorite books on \\shares\for-all
parmenides' favorite books on \\shares\for-all

(Not that I would generally recommend having such filenames. But the
possibility exists and one should know how to deal with it.)

In any case, ls(1) is to be preferred over “echo” here because it lists one
filename per line (provided that it does not contains newline). A possible
exception is a for–in loop.

--
PointedEars

Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.

Chris F.A. Johnson

unread,
Feb 2, 2015, 3:08:07 PM2/2/15
to
On 2015-01-31, Thomas 'PointedEars' Lahn wrote:
...
> In any case, ls(1) is to be preferred over ???echo??? here because it lists one
> filename per line (provided that it does not contains newline).

Why would you use an external command (ls)?

printf "%s\n" * ## Adjust pattern to taste

--
Chris F.A. Johnson

Thomas 'PointedEars' Lahn

unread,
Feb 4, 2015, 3:58:29 PM2/4/15
to
Chris F.A. Johnson wrote:

> On 2015-01-31, Thomas 'PointedEars' Lahn wrote:
>> In any case, ls(1) is to be preferred over ???echo??? here because it
>> lists one filename per line (provided that it does not contains newline).
>
> Why would you use an external command (ls)?

For example, because it has more file-related features.

> printf "%s\n" * ## Adjust pattern to taste

That is equivalent to “ls *” and more elegant than it. However, note that
printf(1) can be an external command, too.

Kaz Kylheku

unread,
Feb 4, 2015, 4:58:24 PM2/4/15
to
On 2015-02-04, Thomas 'PointedEars' Lahn <Point...@web.de> wrote:
> Chris F.A. Johnson wrote:
>
>> On 2015-01-31, Thomas 'PointedEars' Lahn wrote:
>>> In any case, ls(1) is to be preferred over ???echo??? here because it
>>> lists one filename per line (provided that it does not contains newline).
>>
>> Why would you use an external command (ls)?
>
> For example, because it has more file-related features.
>
>> printf "%s\n" * ## Adjust pattern to taste
>
> That is equivalent to “ls *” and more elegant than it. However, note that
> printf(1) can be an external command, too.

If printf *is* an external command, then you can run into an argument limit
limits in passing the expansion of * to that command.

This is not a problem with plain "ls", whether or not it is built in.

Chris F.A. Johnson

unread,
Feb 5, 2015, 3:08:07 PM2/5/15
to
On 2015-02-04, Thomas 'PointedEars' Lahn wrote:
> Chris F.A. Johnson wrote:
>
>> On 2015-01-31, Thomas 'PointedEars' Lahn wrote:
>>> In any case, ls(1) is to be preferred over ???echo??? here because it
>>> lists one filename per line (provided that it does not contains newline).
>>
>> Why would you use an external command (ls)?
>
> For example, because it has more file-related features.

If the reason for preferring ls is "because it lists one filename
per line", then other file-related features are irrelevant.

>> printf "%s\n" * ## Adjust pattern to taste
>
> That is equivalent to ???ls *??? and more elegant than it.

No, it is not equivalent to 'ls *'.

It is equivalent to 'ls -d *'.

> However, note that
> printf(1) can be an external command, too.

Yes, printf *is* also an external command, but it is a builtin in
all the major shells.

--
Chris F.A. Johnson

Thomas 'PointedEars' Lahn

unread,
Feb 5, 2015, 4:23:18 PM2/5/15
to
Chris F.A. Johnson wrote:

> On 2015-02-04, Thomas 'PointedEars' Lahn wrote:
>> Chris F.A. Johnson wrote:
>>> On 2015-01-31, Thomas 'PointedEars' Lahn wrote:
>>>> In any case, ls(1) is to be preferred over ???echo??? here because it
>>>> lists one filename per line (provided that it does not contains
>>>> newline).
>>> Why would you use an external command (ls)?
>> For example, because it has more file-related features.
>
> If the reason for preferring ls is "because it lists one filename
> per line", then other file-related features are irrelevant.

No, you can simply add “-l”, for example, to obtain a different result, more
details. You cannot simply do something like that with the “printf”
approach.

But now I think that an approach that uses ls(1) is not limited by the
number of parameters in a command is a stronger reason to prefer it over any
approach that use “*”, including the “printf” one.

>>> printf "%s\n" * ## Adjust pattern to taste
>>
>> That is equivalent to ???ls *??? and more elegant than it.
>
> No, it is not equivalent to 'ls *'.
>
> It is equivalent to 'ls -d *'.

ACK.

>> However, note that
>> printf(1) can be an external command, too.
>
> Yes, printf *is* also an external command, but it is a builtin in
> all the major shells.

“Major” is a “weasel word”; because, who defines what can be considered
“major”? What matters is that there is no requirement that it be a builtin,
so it is a fallacy to argue in favor of “printf” merely because it were a
builtin.

Chris F.A. Johnson

unread,
Feb 5, 2015, 5:08:14 PM2/5/15
to
On 2015-02-05, Chris F.A. Johnson wrote:
...
>>> printf "%s\n" * ## Adjust pattern to taste
>>
>> That is equivalent to ???ls *??? and more elegant than it.
>
> No, it is not equivalent to 'ls *'.
>
> It is equivalent to 'ls -d *'.

More correctly, it is equivalent to 'ls -d1 *'.

--
Chris F.A. Johnson

Thomas 'PointedEars' Lahn

unread,
Feb 8, 2015, 8:58:58 AM2/8/15
to
It depends on the context. Fortunately, the “-1” option of ls(1) is
optional when stdin is not connected to a tty and when neither of “-C”, “-
m”, or “-x” is present, as is common when it is invoked from a shell script.

<http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html>,
section “STDOUT”

GNU ls(1) (from the coreutils) 8.23 is POSIX-compliant in that regard.
0 new messages