cat < file prints the contents of file to stdout.

cat > file reads stdin until Ctrl+D is detected and the input text is written to file.

cat <> file, at least in my version of Bash, prints the contents of file happily (without error), but doesn't modify the file nor does it update the modification timestamp.

How does the Bash standard justify the seemingly ignored > in the third statement - and, more importantly, is it doing anything?

up vote 44 down vote accepted

Bash uses <> to create a read-write file descriptor:

The redirection operator

[n]<>word

causes the file whose name is the expansion of word to be opened for both reading and writing on file descriptor n, or on file descriptor 0 if n is not specified. If the file does not exist, it is created.

cat <> file opens file read-write and binds it to descriptor 0 (standard input). It's essentially equivalent to < file for any sensibly-written program, since nobody's likely to try writing to standard input ordinarily, but if one did it'd be able to.

You can write a simple C program to test that out directly - write(0, "hello", 6) will write hello into file via standard input.

<> should also work in any other POSIX-compliant shell with the same effect.

  • 1
    Writing... to stdin?... Is there any valid use case for this? – Qix Oct 27 '14 at 5:46
  • 3
    Off-hand, I can't think of any good one. Giving an explicit descriptor (4<>file) is useful, and I suppose 0 is as good a default as any when you leave it out. Reading from stdout isn't any better. – Michael Homer Oct 27 '14 at 5:49
  • 3
    <> is also useful on some systems (like Linux) to open named pipes without blocking until another process opens it for writing. – Stéphane Chazelas Oct 27 '14 at 10:59
  • 1
    @Qix: Well write(0, "Password: ", 10) is a good way to prompt for a password if you intend to prompt on anything kind of like a tty. I'm used to seeing it only on stderr but no reason in particular the same technique doesn't work on stdin. – Joshua Oct 27 '14 at 15:20
  • 3
    @Qix - from the POSIX Rationale - The <> operator could be useful in writing an application that worked with several terminals, and occasionally wanted to start up a shell. That shell would in turn be unable to run applications that run from an ordinary controlling terminal unless it could make use of <> ... such as ... the pager more, which reads from standard error to get its commands, so standard input and standard output are both available for their usual usage. cat food | more - >/dev/tty03 2<>/dev/tty03 – mikeserv Oct 28 '14 at 11:26

<> file opens the file (on file descriptor 0 (stdin) by default, like <) in read+write mode without truncation and creating the file if it didn't exist beforehand.

That corresponds to the O_RDWR|O_CREAT flags passed to the open() system call. By contrast < is O_RDONLY and > is O_WRONLY|O_CREAT|O_TRUNC and >> O_WRONLY|O_CREAT|O_APPEND.

Having stdin writable is not often useful as applications usually don't write to their stdin. Applications usually don't expect to read and write on a file descriptor they receive on startup; they usually read from stdin (or a file descriptor they open themselves) and write to stdout or stderr (or a file descriptor they open themselves).

<> can have its uses:

  • You may prefer cat <> file over cat < file if you don't want the command to fail if file doesn't exist, but an empty file created instead.
  • The non-truncating aspect of <> makes it useful to overwrite files in place. In that case however, you generally don't use it on file descriptor 0:

    printf xxx 1<> file
    

    replaces the first 3 bytes of file with xxx.

  • On some systems like Linux, <> on a named pipe (FIFO) opens the named pipe without blocking (without waiting for some other process to open the other end), and ensures the pipe structure is left alive. For instance in:

    mkfifo pipe; sed 's/foo/bar/g' <> pipe
    

    sed handles incoming data from any number of other processes writing to it and never sees eof.

  • Note that on AT&T ksh93, <> defaults to 1<> (stdout) instead of 0<> (stdin). This is a POSIX compliance bug which I reported and will be fixed in the next release. github.com/att/ast/issues/75 But until current ksh93 versions fall out of use, you have to include the file descriptor number to use <> portably. – Martijn Dekker Apr 16 at 3:47

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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