[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [coreutils] basename/dirname can't handle stdin?

From: Eric Blake
Subject: Re: [coreutils] basename/dirname can't handle stdin?
Date: Thu, 13 Jan 2011 16:48:46 -0700
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv: Gecko/20101209 Fedora/3.1.7-0.35.b3pre.fc14 Lightning/1.0b3pre Mnenhy/0.8.3 Thunderbird/3.1.7

On 01/13/2011 04:15 PM, Jeff Blaine wrote:
> So then, please review.  One question at the bottom.
> # Most basic usage
> basename /foo/bar.txt                               => bar.txt
> # Old/current "basename NAME SUFFIX" compat-
> # ibility
> basename /foo/bar.txt .txt                          => bar
> # ERROR, one too many operands
> basename /foo/bar.txt /x.txt /y.txt                 => ERROR

BSD does:

basename /foo/bar.txt /x.txt /y.txt                 => bar.txt

No need to be gratuitously different (using 3 arguments falls outside
the bounds of POSIX, so we can do whatever we want - our current
behavior is to error, but we might as well match BSDs behavior of being
an argument filter without requiring -a, for all cases except 0 and 2

> # BSD-adopted flag to signify no args are a
> # suffix, process all
> basename -a /foo/bar.txt /x/y.txt                   => bar.txt
>                                                        y.txt

Correct, but this raises the issue of ambiguous output if input contains
newlines.  And since it is not a case of --files0-from, maybe it argues
that we need two options, such that:

basename -a -z /foo/bar.txt /x/y.txt => bar.txt\0y.txt\0

and have --files0-from imply -z (similar to how sort has both
--files0-from and --zero-terminated).

> # For completeness, showing 3 args with -a
> basename -a /foo/bar.txt /x/y.txt /a/b.txt          => bar.txt
>                                                        y.txt
>                                                        b.txt
> basename -s .txt -a /foo/bar.txt /x/y.txt /a/b.txt  => bar
>                                                        y
>                                                        b

Also possible with 2 args and without -a:

basename -s .txt /foo/bar.txt /x/y.txt => bar

> # No args means read stdin (-f,--filter mode)
> cat filelist.txt | basename                         => bar.txt
>                                                        y.txt
>                                                        b.txt

Useless use of cat :)

Hmm - BSD doesn't have a stdin filter mode.  Right now:


triggers a usage message for both GNU and BSD basename, but turning it
into a stdin filter by default for 0 arguments means that you will then
hang waiting for stdin, that can lead to surprises for unsuspecting users.

So maybe it's better to require an explicit argument (but see more
thoughts below):

basename --filter < filelist.txt       => bar.txt

basename                               => usage error

> # Only "-s <arg>" means read stdin (-f,--filter
> # mode)
> cat filelist.txt | basename -s .txt                 => bar
>                                                        y
>                                                        b

BSD rejects this usage, too.  With an explicit option:

basename --filter -s .txt < filelist.txt    => bar

> # Handle NUL-terminated stdin
> find / -print | basename --file0-from=-             => bar.txt
>                                                        y.txt
>                                                        b.txt

Typos: you meant 'find / -print0', and --files0-from.  But yes,
--files0-from implies being a stdin filter, so here's a case where you
don't need two options, one was enough.  On the other hand, since we
KNOW the input is NUL-terminated, it seems like the output should be
NUL-terminated as well (in wc and sort, where the data read from
--files0-from is not part of the output, and thus sort --files0-from
does not imply --sort -z; but for basename, it makes sense that the
implication should be there - if you were worried about newline
ambiguity on input, then you should also worry about it on output):

find / -print0 | basename --files0-from=- => bar.txt\0y.txt\0b.txt\0

> # Handle NUL-terminated stdin with suffix strip
> # (assuming /hh has our 3 files in it and is
> # readable)
> find /hh -print | basename --file0-from=- -s .txt   => bar
>                                                        y
>                                                        b

Same typos and issue with NUL-terminated output:

find /hh -print0 | basename --files0-from=- -s .txt   => bar\0y\0b\0

> # Handle NUL-terminated FILE input
> find / -print | basename --file0-from=FILE          => bar.txt
>                                                        y.txt
>                                                        b.txt

This should discard stdin input from find, and only process from FILE;
so that it is identical to:

basename --files0-from=FILE   => bar.txt\0y.txt\0b.txt\0

> etc...
> Is "-f,--filter" necessary?

I don't want to burn -f until we have to; we have to burn -a and -s to
match BSD, but everything else can be a long option until we are sure it
is useful enough to promote to a short option.  Then again, if we add
both --files0-from and --filter, we are stuck with an ambiguous prefix,
and you can't use --f (it would have to be --file or --filt).  That
doesn't seem nice, either.

I guess it all boils down to whether we think:


should hang or automatically become a filter.  If we want to avoid hangs
by requiring an explicit option, then we need something (but can we come
up with a better name than --filter, so that --files0-from can be
unambiguously shortened to --f)?  But since the context of 0 arguments
is unambiguous, and the most obvious choice of an explicit name is
--filter, I'm leaning 60:40 to having just --files0-from, and not --filter.

Eric Blake   address@hidden    +1-801-349-2682
Libvirt virtualization library

Attachment: signature.asc
Description: OpenPGP digital signature

reply via email to

[Prev in Thread] Current Thread [Next in Thread]