I have come across the command line wc < f1 f2
and it's not clear for me what is happening under the hood:
$ echo -n 'a' > f1
$ wc f1
0 1 1 f1
$ echo -n 'bb' > f2
$ wc f2
0 1 2 f2
$ wc < f1 f2
0 1 2 f2
Here the standard input of wc
is being redirected to file f1
, but I'm also passing file f2
as argument. The output I get is as if I had typed wc f2
, i.e.., the standard input is not considered by wc
, it seems.
Is wc
discarding its standard input (wherever it points to) when it also gets passed a file as argument?
Is wc
internally still handling two file descriptors, one for standard input and another for the file it's being passed as argument, or is it the kernel to "unplug" the standard input file descriptor from file f1
and plug it to file f2
later, in this case?
What else, or what IS actually happening, in a command line like wc < f1 f2
?
I am using the Bash shell in Ubuntu 22.04.
Thanks
Here the standard input of
wc
is being redirected to filef1
, but I'm also passing filef2
as argument. The output I get is as if I had typedwc f2
, i.e.., the standard input is not considered bywc
, it seems.
Yes. wc
reads its standard input if and only if either
-
is provided, which explicitly represents the standard input.Note that multiple inputs can be specified on the command line, -
among them, though it is not useful to specify -
more than once.
This is all documented in the manual, albeit a but more concisely.
Is wc discarding its standard input (wherever it points to) when it also gets passed a file as argument?
No, it's just not reading anything from its standard input in that case. And that's usually what you want when you ask it to read from a file. Rarely do you want it to try to read interactive input from the keyboard, for example, but that's what its stdin is connected to when you run wc
interactively and do not redirect.
Is
wc
internally still handling two file descriptors, one for standard input and another for the file it's being passed as argument, or is it the kernel to "unplug" the standard input file descriptor from file f1 and plug it to file f2 later, in this case?
That's unspecified, but certainly not a matter of kernel behavior. What I would expect, especially in light of wc
's behavior around multiple filename arguments and the -
argument, is that wc
opens and processes each named file in turn, or uses the stdin
provided by the system when the current argument is -
. I would be surprised to find that it did any internal I/O redirection.
What else, or what IS actually happening, in a command line like
wc < f1 f2
The redirection < f1
is parsed by the shell and processed separately from the command line arguments. The shell performs the corresponding redirection before handing off control to wc
. The redirection operator tokens do not constitute command-line arguments themselves, so the wc
command sees only the effect of the redirection, but not the redirection operator itself. Among the consequences is that wc < f1 f2
is functionally equivalent to wc f2 < f1
.
wc
, for its part, behaves as documented. At least one filename argument having been specified, it counts the contents of the indicated file only. If you want it to count first the data redirected from its standard input and then the contents of file f2
, then that would be
wc - f2 < f1
(for example).