155

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
  • 4
    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 Commented Dec 23, 2014 at 20:04
  • There are also 2>&- construction, which means "close descriptor 2". Commented Dec 2, 2016 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. Commented Dec 9, 2016 at 12:32

6 Answers 6

220

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.


¹ Except for the >& filename operator that bash eventually copied from csh to redirect both stdout and stderr, where >&- is still about closing file descriptors like in the Bourne shell, even when - is quoted or the result of an expansion which means that >& operator can't be used for arbitrary file names. Use the standard/Bourne > "$file" 2>&1 syntax or the bash-specific &> "$file" instead.

8
  • 52
    It's worth adding that /dev/stdin and /dev/stdout are universally available and can be used in place of the - convention. Commented Jul 22, 2011 at 9:00
  • 15
    @jmtd: /dev/std{in,out} are not universally available. Not all unixes have it. Commented Jul 22, 2011 at 10:37
  • 2
    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? Commented Aug 2, 2011 at 8:51
  • 1
    @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? :) Commented Nov 23, 2016 at 6:29
  • 3
    @jmtd I seem to have found a tentative answer to the question: unix.stackexchange.com/a/278368/31669 Commented Nov 23, 2016 at 6:35
22
  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.

14

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

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

0

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

2
  • The redirection is interpreted by the shell, not the program being invoked. Commented Jan 3, 2017 at 13:46
  • If /dev/stdout exists at all, it may be a symbolic link to /dev/fd/1 as you say, but it may also be a symbolic link to /proc/self/fd/1 or it may be a character special device file, depending on what Unix you're on. See also unix.stackexchange.com/questions/36403/… Commented Apr 26, 2024 at 6:49
-1

Special characters have mostly two meanings:

ASCII numeric chart.

Scripting or symbolic.

It's possible that a single character represents a string, or act as a string. as my understanding.

in C language fopen() function takes two arguments first file stream and the second mode in which file will be open. the mode is a string. even if it's single character.

cat > "-" works.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.