Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I wrote a 10000010-byte file (99010 rows of 100 consecutive a's) named big for experimentation purposes. I then copied the entire text into my clipboard, ran wc, and pasted it into stdin. Next, I did a simple redirection that's supposed to have the exact same effect. But this is what I got:

$ wc[Enter]
[paste 99010 lines of garbage copied directly from `big']
  99010   99010 10000010
$ wc < big
   99010    99010 10000010

Notice the different field widths. My best guess is that the first result was printed with "%7d %7d %7d", and the second with "%8d %8d %8d".

Can someone please explain how this is possible? I'm of the impression that, as far as wc is concerned, the input for the second experiment is coming from stdin as well (because the shell takes care of < big, so wc shouldn't even know that I typed that), so theoretically wc should have done the same exact thing twice, but it clearly did not. What am I not understanding about redirection?

Edit: I don't think this really matters, but I did $ cat big | xclip -selection clipboard to copy the data into my clipboard, then I simply right-clicked in gnome-terminal and pasted it in. Just in case anyone wants to try this out on their computer.

share|improve this question
add comment

1 Answer

up vote 2 down vote accepted

The wc implementation from GNU coreutils tries to optimize the width of the columns. If you pass it only regular files (whether on standard input or by name), it reads each the directory entry for each file to know the file size, and it knows that all the numbers it's going to print are smaller or equal to the sum of the sizes of the files. With regular files, wc adjusts the width of the column accordingly. If at least one of the input files isn't a regular file, GNU wc uses a default width of 7 (which may prove out too small, so you get a lot of extra space, or too big, so you get unaligned columns).

share|improve this answer
    
Right, I kinda got that when I read the source code. But my question is, how does it know I'm passing it a regular file when I use <? How does it even know the file name or where the file is? Isn't the shell supposed to translate < big before it even gets to wc? –  paul Sep 8 '12 at 18:21
    
To clarify, I do expect wc big to print "%8d %8d %8d" because in this case, the file name is a direct argument to wc, so it can optimize whatever it wants with knowledge of the file name. But I do not expect wc < big to print "%8d %8d %8d"; instead I'm expecting "%7d %7d %7d" because wc should think that its only argument is stdin, which isn't a regular file, so it should use a default width of 7, no? –  paul Sep 8 '12 at 18:26
    
@paul wc isn't acting based on the file name, it's acting based on the type of file (regular file, pipe, character device (which includes terminals), …). Standard input may or may not be a regular file, depending on where you've redirected the input from. If GNU wc's standard input is a regular file, it computes the size first, otherwise it uses a standard width — same as if you'd passed the file name on the command line. –  Gilles Sep 9 '12 at 17:56
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.