Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Your mentioning people “start[ing] using [commands] in ways their programmers never imagined” reminded me, a shell newbie, of something I had read a long time ago, which was that people who use `cat` to output a single file’s contents are using the program for something other than its intended purpose. That inspired me to experiment to find the correct way of echoing file contents.

I think the correct way is the `<` operator. `>` writes to a file, and `<` is the inverse, so it reads from a file. One shouldn’t `cat some-file.txt` or `cat some-file.txt | wc -l`; one should `< some-file.txt` or `< some-file.txt | wc -l`. `cat` is only necessary when you supply to it multiple arguments, as in `cat first-file.txt second-file.txt`.

Of course, `cat` still works for outputting file contents, as it has for me all this time. But it just feels more “right” and “safe” to use the operator that is built for that purpose.

I just wanted to mention that discovery in case anyone else wondered the same thing when they read the words about using commands in unintended ways.



    $ < some-file.txt | wc -l
doesn't work. You should run

    $ wc -l <some-file.txt
Although in most cases the program you're using is capable of reading from both stdin and from a file. So you'd really just run

    $ wc -l some-file.txt
When you see characters like '|', '<', and '>' the things you're playing with are called pipes. (There's a decent wikipedia article on 'Pipeline (UNIX)' that talks more about them) Having tons of commands that do specific things wouldn't be very useful if you couldn't compose them (in the function composition sense), and pipes are the tools you use to combine them. This is where the 'using commands in ways never imagined by their authors' really comes from.


To be pedantic, > and < aren't pipes, only | is. A pipeline means that stdout of the first program is stdin for the next program. > and < set stdout or stdin to a file, not another program.

http://en.wikipedia.org/wiki/Pipeline_%28Unix%29

http://en.wikipedia.org/wiki/Redirection_%28computing%29


I assume he meant:

  $ < some-file.txt ws -l
(without the pipe). '<' works at the beginning of the command just as well as it works at the end, meaning you can basically do:

  s/^cat \(.*\)|/\<\1


Given the proximity of `<` and `>`, and the fact that `> somefile.txt` will silently truncate the file, I would take issue with the "safeness" claim :P

Also, `< file.txt | wc` doesn't work (at least not in bash; zsh (my install/plugin combo, at least) apparently tries to map the lone `< file.txt` to `less -R file.txt`...which spits out an error. Anyway, omitting the pipe will work: `< file.txt wc -l`

`cat` by definition concatenates one or more files and spits the output to stdout, so using it on a single file is perfectly within the bounds of its definition (IMHO; I realize people get really zealous about this type of thing and I'm not trying to start a war).


> and the fact that `> somefile.txt` will silently truncate the file

Bash has the "set -C" option to toggle on "no-overwrite" mode for redirection operators.


zsh also has a "setopt NO_CLOBBER", but it's also not the default (unfortunately).

Default behavior:

  % touch foo
  % echo bar > foo
  % cat foo
  bar
  % rm foo
No clobber mode:

  % setopt NO_CLOBBER
  % touch foo
  % echo bar > foo
  zsh: file exists: foo
Manual override:

  % echo bar >| foo
  % cat foo
  bar


But it's obnoxiously not set by default.


This might screw up some POSIX shell scripts if they expect to be able to write a tmp file or overwrite one if it already exists.


Cat catenates, it doesn't nearly always concatenate :-)


cat will actually launch a separate process, while redirection will not. Unless you're working on a very old machine or a low-spec embedded system, this shouldn't make much practical difference.

"< some-file.txt | wc -l" doesn't work for me. "< some-file.txt wc -l" does. I actually wasn't aware of the latter syntax; and now that I think about it, I'm actually not sure if I've ever used redirection in combination with piped commands.

(I don't do a whole lot of shell scripting, and I exclusively used DOS, Windows, and OS/2 during my most formative years, so my reflex is to reach for an actual programming language to do nontrivial things, because even though I've been using Linux for years as my main OS, the fact that I now have a competent shell available still hasn't completely sunk in. I was amazed when I discovered the xargs command and its --max-procs option; I'd written a Python script to do much the same thing.)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: