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.

/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.
(there's still the case of echo test | cat -- *.txt - or
cat -- "$file" - though)

But then, the same would have to be done for all GNU utilities
for consistency. But then there are utilities like paste, join,
comm where that would not be desirable, so probably not a good
idea in the end (see also how paste - - doesn't work the same as
paste /dev/stdin /dev/stdin even on systems other than
Linux/Cygwin)..

Note that gawk already does it in

gawk -E file.awk "$file"

Where using -E (as opposed to -f) fixes that problem and the one
about "var=value.txt" being treated as a variable assignment and
that other options are still processed by awk.

[...]
> If you wish to cat a file named '-' in the current directory, spell it
> './-' or use an absolute path to that file.  That's true of all command
> line utilities that treat '-' as stdin (not just cat).
[...]

Or in a shell, use:

cat < "$file"

Or

cat - < "$file"

(but not cat -- - < "$file" ;-)

To concatenate arbitrary files, ironically you can do:

cat /dev/stdin /dev/fd/3 < "$file1" 3< "$file2"

Which also has the benefit (or not) of not outputting anything
if any of the files can't be opened.

2019-07-05 23:48:17 -0500, Eric Blake:
[...]
> 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. 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.

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).

-- 
Stephane


Reply via email to