48

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?

2 Answers 2

54

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.

13
  • 1
    Writing... to stdin?... Is there any valid use case for this? Oct 27, 2014 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. Oct 27, 2014 at 5:49
  • 1
    While reading from stdout is generally not useful, 1<> the-file often is as it also does not truncate the-file. <> was introduced by the Bourne shell, so would work in any Bourne-like shell. Oct 27, 2014 at 7:20
  • 6
    <> is also useful on some systems (like Linux) to open named pipes without blocking until another process opens it for writing. Oct 27, 2014 at 10:59
  • 4
    @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, 2014 at 11:26
48

<> 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.

4
  • 2
    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. Apr 16, 2018 at 3:47
  • @MartijnDekker, I know, I was the one telling you about it in the first place ;-). Note that it's only for ksh93t+ (where the behaviour changed) and above. Sep 4, 2018 at 16:27
  • 1
    What are (or were) the systems unlike Linux where mkfifo fifo; exec 3<>fifo would block? May 29, 2019 at 15:44
  • @UncleBilly, I wouldn't remember. POSIX leaves it undefined if you open a fifo with O_RDWR. Jan 22, 2020 at 16:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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