For a command, if using - as an argument in place of a file name will mean STDIN or STDOUT.

  1. But in this example, it creates a file with the name -:

    echo hello > -
    

    How can I make - in this example mean STDOUT?

  2. Conversely, how can I make - mean a file named - in examples such as:

    cat -
    
  • 3
    Since I apparently have to have 50 reputation to comment directly... On the /dev/stdin /dev/stdout comment, AIX, which is a legitimate UNIX derivative does not have these pseudodevices. And, as a further comment, LINUX is not a UNIX derivative in any case. It is a POSIX-compliant workalike, and the most popular of the UNIX-ish OS's at this point, but make no mistake, this is no UNIX. But, the gist of the replies here are correct. The "-" notation is not interpreted as special by the shell, and is thus passed directly to each individual application as an ARG. If the application does not recogni – user95873 Dec 23 '14 at 20:04
  • There are also 2>&- construction, which means "close descriptor 2". – user3132194 Dec 2 '16 at 5:58
  • @user95873, what I suppose you wanted to say is: while Linux is Unix-like, not every Unix-like (or true UNIX) is Linux. The matter whether Linux is or isn't true UNIX (i.e. complies the Single UNIX Specification) doesn't have relation to /dev/std{in,out,err} issue. As /dev/std{in,out,err} is added feature, not missing. – sasha Dec 9 '16 at 12:32
up vote 118 down vote accepted

Using - as a filename to mean stdin/stdout is a convention that a lot of programs use. It is not a special property of the filename. The kernel does not recognise - as special so any system calls referring to - as a filename will use - literally as the filename.

With bash redirection, - is not recognised as a special filename, so bash will use that as the literal filename.

When cat sees the string - as a filename, it treats it as a synonym for stdin. To get around this, you need to alter the string that cat sees in such a way that it still refers to a file called -. The usual way of doing this is to prefix the filename with a path - ./-, or /home/Tim/-. This technique is also used to get around similar issues where command line options clash with filenames, so a file referred to as ./-e does not appear as the -e command line option to a program, for example.

  • 27
    It's worth adding that /dev/stdin and /dev/stdout are universally available and can be used in place of the - convention. – jmtd Jul 22 '11 at 9:00
  • Also in the cat case, using redirection instead of listing the argument might help: cat <-; however, it would be hard to mix and match that with concatenating more than one file at a time. – jmtd Jul 22 '11 at 9:02
  • 7
    @jmtd: /dev/std{in,out} are not universally available. Not all unixes have it. – camh Jul 22 '11 at 10:37
  • 1
    Interesting, I assumed they were part of POSIX (but can't confirm). They're present at least on Linux, the BSDs and Solaris. Can you give an example of a modern UNIX that lacks them? – jmtd Aug 2 '11 at 8:51
  • @camh Not sure if you got the notification, and this is a very, very old topic; I'm not sure if you can, but I'm very curious if you know the answer to jmtd's question? :) – Swivel Nov 23 '16 at 6:29
  1. Instead of echo hello > -, you can use echo hello > /dev/stdout.

    While '-' is a convention that has to be implemented by each program wanting to support it, /dev/stdin, /dev/stdout and /dev/stderr are, when supported by the OS (at least Solaris, Linux and BSDs do), independent of the application and then will work as you intend.

As camh mentioned, - is just a naming convention used by some programs. If you want to refer to these streams with a file descriptor the shell will recognize, jiliagre was correct in having you use the name /dev/stdin or /dev/stdout instead. Those file names should work any place a normal file name would work.

  1. That being said, your first example is kind of silly. Any output that would be caught by the redirect operator to write to a file is already ON standard-output, so redirecting it and writing it back to where it came from is useless. The behavior you use there is the pipe, not a redirect:

    echo hello |
    
  2. In your second example you simply need to give can some indication that you want a litteral file of that name, not the internal alias it has. You can do this easiest by specifying a path to the file like this:

    cat ./-
    

As for 1, the program has to support it. You can't just arbitrarily use it. As for 2, redirect input from (e.g., cat < -).

The '-' approach has a lot of problems. First of all it requires an interpretation of the '-' character and many programs don't perform such interpretation. And furthermore, there are some programs that interpret an hyphen as a delimiter marking the end of command line options. The programs are written to work with filename arguments, the '-' approach is an hack, nice but weak.

The best way is:

$ echo hello > /dev/fd/1

/dev/stdout is a symbolik link of /dev/fd/1

  • The redirection is interpreted by the shell, not the program being invoked. – sherrellbc Jan 3 '17 at 13:46

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.