Reputation: 147
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
Upvotes: 2
Views: 220
Reputation: 181179
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 bit 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, 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).
Upvotes: 2
Reputation: 9875
Is
wc
discarding its standard input (wherever it points to) when it also gets passed a file as argument?
Ignoring stdin
if file arguments are specified is normal behavior for many commands. This is done by the program itself, i.e. by the wc
program in this case.
Often you can use -
as a command line argument to use stdin
like an ordinary file specified on the command line.
This behavior is defined by the POSIX specification for wc
. My understanding of "...and the implementation treats the '-' as meaning standard input" is that it depends on the implementation if -
means standard input or a file named -
.
Citing https://man7.org/linux/man-pages/man1/wc.1p.html
STDIN
The standard input shall be used if no file operands are specified, and shall be used if a file operand is '-' and the implementation treats the '-' as meaning standard input. Otherwise, the standard input shall not be used. See the INPUT FILES section.
Example:
$ wc foo bar
1 1 4 foo
2 2 8 bar
3 3 12 total
$ wc foo < bar
1 1 4 foo
$ wc < foo bar
2 2 8 bar
$ wc - bar < foo
1 1 4 -
2 2 8 bar
3 3 12 total
$ wc < foo - bar
1 1 4 -
2 2 8 bar
3 3 12 total
$ echo foo | wc - bar
1 1 4 -
2 2 8 bar
3 3 12 total
Upvotes: 1
Reputation: 141698
What else, or what IS actually happening, in a command line like wc < f1 f2?
wc < f1 f2
executes wc f2 <f1
- executes command wc
with one argument f2
and redirects file f1
to standard input.
wc f2
just prints the counts for file f2
. Nothing happens to standard input.
Is wc discarding its standard input
No, there is no "discarding", there is "ignoring". wc
does not touch standard input at all. "Discarding" would imply the standard input is fully read after wc
exits, but it is not.
Is wc internally still handling two file descriptors
No, wc
is "handling" only f2
file - opening and reading it. You can see what system calls wc
is doing by using strace wc f2
.
is it the kernel to "unplug" the standard input file descriptor from file f1 and plug it to file f2 later, in this case?
There is no "unplugging".
Upvotes: 1