coreutils
[Top][All Lists]
Advanced

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

Re: [PATCH] cat: open any file name after "--"


From: Eric Blake
Subject: Re: [PATCH] cat: open any file name after "--"
Date: Sat, 6 Jul 2019 07:19:50 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.7.0

On 7/6/19 4:14 AM, Stephane Chazelas wrote:
> 2019-07-05 23:31:06 -0500, Eric Blake:
> [...]
>> Sorry, but this patch violates POSIX.
>>
>> https://pubs.opengroup.org/onlinepubs/9699919799/toc.htm
>>
>> "If a file is '-', the cat utility shall read from the standard input at
>> that point in the sequence."
> [...]
> 
> But coreutils could do that when not under $POSIXLY_CORRECT, as
> that's admitedly a design flaw, and is quite annoying to have to
> do
> 
> case $file in
>  (-) file=./-;;
> esac
> cat -- "$file"
> 
> to work around it.

How often does one literally expect to cat the contents of a file named
'-'? If you have $file containing user-supplied input, it's just as easy
to do:

case $file in
  -*) file=./$file ;;
esac
cat "$file"

for the same behavior for ALL files starting with '-' that are not to be
confused with options, rather than just bypassing '-' for stdin.

> 
> /dev/stdin could be seen as a fix to that misdesign, but not on
> Linux or Cygwin (where for instance cat /dev/stdin /dev/stdin
> does not work the same as cat - - unless stdin is a pipe for
> instance).
> 
> It's unlikely people would use "cat -- -" and expect that "-" to
> mean stdin, so it would be unlikely to break existing scripts.

Anyone knowing they want to cat "-" can just as easily directly write
"cat ./-"; it's really only when you have an arbitrary user-supplied
$file where you don't specifically know which file name you want to
open, and where you want to ensure the user's input is not confused with
an option or with stdin.

> (there's still the case of echo test | cat -- *.txt - or
> cat -- "$file" - though)

"cat -- *.txt -" should concatenate all files ending in .txt plus stdin.
If it cat's a file named "./-", then you've proven that this patch is a
misfeature.


>> For more fun, go figure out why:
>>
>> grep - - --
>> grep [---]
>>
>> behave the same, regardless of whether you have a file named '-' in your
>> current working directory (unless you use shopt -s failglob).  And the
>> rule on using ./- for a file in the current directory also applies to
>> touch, except there '-' means stdout instead of stdin.
> 
> Only with GNU grep or compatible and when $POSIXLY_CORRECT is
> not in the environment.

True - whether '--' is a filename or the end-of-option marker depends on
whether argument permuting is permitted (GNU) or forbidden
(POSIXLY_CORRECT).  But I definitely gave you food for thought, and you
took the bait :)

> That's another misfeature IMO, but this
> time introduced by GNU and not *allowed* by POSIX.
> 
> in "grep - - --", while for grep POSIX leaves it undefined
> whether "-" is treated as stdin or not, that "--" is required to
> be a file argument since it comes after a non-option argument.
> So that would likely report an error about a missing "--" file.
> 
> That means that while:
> 
> grep - *.txt
> 
> is fine for POSIX compliant grep implementations, in GNU grep,
> you need:
> 
> grep -- - *.txt
> 
> or
> 
> grep -e - -- *.txt
> 
> About:
> 
> grep [---]
> 
> With bash, beside failglob, nullglob would also change the
> behaviour. Also, the behaviour of ranges is unspecified in POSIX
> outside of the POSIX locale. It could match (for both glob and
> grep RE) collating elements that are /equivalent/ to - for
> instance.

I was also trying to point out that whether the shell globs [---] to '-'
before grep is invoked, or whether grep performs regexp expansion on
[---] to match only the character '-' after grep is invoked, then you
are still matching a single '-' (and yes, your comment about the C
locale for glob/regexp range expressions is on point).

> 
> That behaviour of GNU touch wrt touch - is not POSIX compliant
> AFAICT (though that's another case where /dev/stdout wouldn't
> work unless "touch" itself treated a "/dev/stdout" argument
> specially).

It is compliant. Guideline 13:
"For utilities that use operands to represent files to be opened for
either reading or writing, the '-' operand should be used to mean only
standard input (or standard output when it is clear from context that an
output file is being specified) or a file named -."

Touch is an output utility (it produces files, not consumes their
contents), so the GNU Coreutils developers determined that it is clear
from context that - can mean stdout (but you are correct that while it
is permitted by POSIX, it is not mandated, and I don't know of other
touch implementations that do the same).

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

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