Hacker News new | past | comments | ask | show | jobs | submit login
Useful use of cat(1) (in-ulm.de)
115 points by gnosis on Feb 26, 2012 | hide | past | favorite | 45 comments



ps has a nasty habit of truncating its output. Piping it into cat is a way around this. E.G.

  $ echo $COLUMNS
  118

  $ ps -fp 14706
  UID        PID  PPID  C STIME TTY          TIME CMD
  root     14706 14705  0 Jan29 pts/3    00:00:00 sudo -p [local sudo] Password:  python /usr/lib/sshuttle/main.py pytho

  $ ps -fp 14706 | cat
  UID        PID  PPID  C STIME TTY          TIME CMD
  root     14706 14705  0 Jan29 pts/3    00:00:00 sudo -p [local sudo] Password:  python /usr/lib/sshuttle/main.py python -v --firewall 12300 0


Most generally, it will trick any command into thinking that it's not writing to a tty ; so piping into cat will often remove colors.


Of course if you want colours, you can often force programs to use them anyway. For example, I use the alias:

  alias new='ls -lthr --color=always | tail'
Normally ls will not use colours when writing to a pipe (not a tty).


Using the -ww flag will produce unlimited width output


Thanks! I'd searched the ps manpage for truncate and length. I don't know why I didn't think to look for width.


"... Piping it into cat is a way around this. ..."

I've always preferred less - lets you scroll backwards & forwards through the piped output.


A very nice (but a bit academic) way to look at "cat" as a monadic "return" on unix pipes :

http://okmij.org/ftp/Computation/monadic-shell.html


Also surprisingly useful in command line video editing. For instance, you can join mpg files together...

cat intermediate1.mpg intermediate2.mpg > intermediate_all.mpg http://ffmpeg.org/faq.html#How-can-I-join-video-files_003f


Well, that's the main purpose of cat - concatenate files and print on the standard output.


Don't forget "tac" - the reverse of "cat".


No, that just concatenates a file reading bytes from the end, backwards.

The real opposite of cat would be a putative 'trunc'. So if you typed

    $ cat somefile
It would print the file to your terminal. And then if you said

     $ trunc somefile
The printed lines would be removed from your terminal. :)


In case you missed it, "tac" is literally the reverse of "cat". As in "cat".reverse() or something.


I get that tac exists and is useful for concatenating and printing files in reverse.

Neilk was just humorously pointing out that since cat stands for concatenate, its reverse should be truncate, and since cat is often abused to print a single file to a terminal this fictional trunc should "unprint" it.

Arguably you could view 'comm -3' as the reverse of cat.

  # output is all the lines of file1 and file2
  cat file1 file2

  # output is the lines in file1 not in file 2, and vice verse
  comm -3 file1 file2


> cat stands for concatenate

I almost resisted the urge, but no, the pedant in me :-) insists on pointing out that cat is short for catenate


  cat > file vs. touch file
  cat file | cmd vs. cmd < file
  cmd1 | cmd2 | cat vs. { cmd1 | cmd2 || true; } vs. cmd1 | cmd2; true
So even some of the thing listed are still not the best use case for cat


| cat > file vs. touch file

With 'cat > file' you can actually type in the file's contents (then press ^d to finish). 'touch file' merely creates an empty file. (Not that I think 'cat > file' is much faster than 'vi file')


Ok, I should read more carefully. I thought the article uses cat > file followed by ^D to create empty files.

Of course when having some text cat > file is just fine.


No, you can remove 'cat' on most shells:

    > file


What shell? I'm running bash 4.2.20(2)-release, and "> file" is behaving like "touch file".


You're right, I was mistaken. It's just in Z shell.


You mean there are other shells?


>* cat file | cmd vs. cmd < file*

I tend to prefer the cat version as the flow of the command follows the left-to-right direction in which I generally read, and it makes things easier for less experienced users to read and understand for the same reason.

It does make things less efficient of course, as there is at least one extra memory-copy of everything and extra process context switching, but in most cases your drives or network are the bottleneck not CPU speed or memory bandwidth. Also, when working on the command line you can drop in useful tools like pv in place of cat.


If you want left to right you can do

    <file cmd


The "convert file into arguments" trick is useful, but a "while read/do" loop would be better:

    cat file | while read INPUT
    do
        command "$INPUT"
    done
... which will read the entire line from 'file' into the shell variable "$INPUT", inclusive of whitespace. If you need to do further parsing, of course, you can do that within the loop.

Trap: since you're creating a subshell (at least in bash/Bourne), variables defined within the loop are NOT defined after it exits.


You may also create new empty files by saying `touch filename`. This saves three keystrokes (which includes an annoying `>` symbol, requiring the shift key) as compared to the aforementioned `cat` method!


what do you mean? "cat > file" allows you to create simple text file not just empty files. As long as you don't need advanced editing, it is the quickest way to do it (well I think).


You are correct; my comment solves a different problem than the one in the article!


Or, at least when running Bash (possibly sh, didn't try), just

   >foo
also works to create file "foo".


That does not work, but

  :>foo
(the happy file creation operator) does.


What do you mean it doesn't work? ">file" will work on all POSIX shells, it even works on Solaris /bin/sh!

Also ":>" is not an operator, it's ":" (a built-in command that does nothing and returns true) and a redirection.


Like the grand-parent, I have definitely used a Unix variant (CX/SX?) which required a command to do redirection.


It was a joke to call it an operator.


You can also use 'echo "hello" > file'


technically the equivalent is

    echo -n > file


Often I find myself dealing with tab-separated files; and cat -n is very handy there.

To see which columns a particular value occurs in:

    awk -F'\t' < tsv-file | tr '\t' '\n' | cat -n | grep something


FYI you can add line numbers (cat -n behavior) within awk directly as so:

    awk '{print NR, $0}'


The nl command (part of coreutils) is specifically written for numbering lines. It can do simple line numbering, along with various other styles and formats.

Its man page can be seen here: http://linux.die.net/man/1/nl


awk's sprintf can do all of that. Not saying it's the right tool for the job, but the parent did have a pipeline already using awk.


Is there a version of awk that has interesting default behavior when you leave out the program like that?


Instead of using a cat with heredoc, just type

    cat - | grep "something"
And control-d when finished entering text


You don't need the dash. This is enough:

  cat | grep "something"


Or just

    grep "something"


When I was young, I used cat and grep like that until an old Unix sys-admin remarked "What a gratuitous use of cat!". At the time, I did not understand what he meant, but now I do. So whenever I see cat and grep used like this, I think back to that lesson I learned.


In some older versions of bash, when dealing with process substitution, you actually needed the dash.

For example

    get_data | tee >(cmd)
    get_data | tee >(cat | cmd)
would fail but

    get_data | tee >(cat - | cmd)
would succeed.


I thought it was a post about cats >.<




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: