25

It's really annoying to type this whenever I don't want to see a program's output. I'd love to know if there is a shorter way to write:

$ program >/dev/null 2>&1

Generic shell is the best, but other shells would be interesting to know about too, especially bash or dash.

Matt Joiner
  • 112,946
  • 110
  • 377
  • 526

9 Answers9

16
>& /dev/null
andrewdotn
  • 32,721
  • 10
  • 101
  • 130
  • Thanks, that's good (didn't know that one) but I should have specified that "shortcut" means less than half the number of characters. This is almost as much typing. In fact the 2>&1 part is easy, it's /dev/null that's annoying to type. –  May 30 '09 at 00:55
  • 3
    I'm really curious to know what you're running that forces you to pipe stdout and stderr to /dev/null so frequently that typing /dev/null becomes an annoyance. – Laurence Gonsalves May 30 '09 at 03:21
  • 9
    Bash manual prefers the form "&>/dev/null", to avoid possible ambiguities with ">&n" (where n is an integer). I don't think it's portable outside of Bash, though. – ephemient May 31 '09 at 02:45
15

You can write a function for this:

function nullify() {
  "$@" >/dev/null 2>&1
}

To use this function:

nullify program arg1 arg2 ...

Of course, you can name the function whatever you want. It can be a single character for example.

By the way, you can use exec to redirect stdout and stderr to /dev/null temporarily. I don't know if this is helpful in your case, but I thought of sharing it.

# Save stdout, stderr to file descriptors 6, 7 respectively.
exec 6>&1 7>&2
# Redirect stdout, stderr to /dev/null
exec 1>/dev/null 2>/dev/null
# Run program.
program arg1 arg2 ...
# Restore stdout, stderr.
exec 1>&6 2>&7
Ayman Hourieh
  • 132,184
  • 23
  • 144
  • 116
  • This should be the accepted answer, I tried to implement this myself but I accidentally ran the "$@" inside a subshell for some reason. This works flawlessly for my use. – SeedyROM Mar 16 '18 at 09:36
12

In bash, zsh, and dash:

$ program >&- 2>&-

It may also appear to work in other shells because &- is a bad file descriptor.

Note that this solution closes the file descriptors rather than redirecting them to /dev/null, which could potentially cause programs to abort.

Zaz
  • 46,476
  • 14
  • 84
  • 101
  • "Can potentially"? I'd call that "usually does". Programs that don't check whether their writes succeed are *buggy*. – Charles Duffy Oct 14 '17 at 12:49
  • If I'm right, `sh` is the name of the default shell for a given distribution, while `dash` is the name given to the Debian version of `ash`. See [wikipedia](https://en.wikipedia.org/wiki/Dash_(shell)). Could you clarify please ? – loxaxs Feb 04 '18 at 13:22
  • @loxaxs: In Ubuntu, `sh` now runs `dash`. I can't remember what it did for me at the time of writing (I seem to recall something about running `bash` in POSIX compatibility mode), but I've removed it now because of the ambiguity. – Zaz Feb 04 '18 at 14:47
7

Most shells support aliases. For instance, in my .zshrc I have things like:

alias -g no='2> /dev/null > /dev/null' 

Then I just type

program no
swampsjohn
  • 6,826
  • 7
  • 37
  • 42
3

Edit: the (:) or |: based solutions might cause an error because : doesn't read stdin. Though it might not be as bad as closing the file descriptor, as proposed in Zaz's answer.


  • For bash and bash-compliant shells (zsh...):

    $ program &>/dev/null
    OR
    $ program &> >(:) # Should actually cause error or abortion
    
  • For all shells:

    $ program 2>&1 >/dev/null
    OR
    $ program 2>&1|: # Should actually cause error or abortion
    

    $ program 2>&1 > >(:) does not work for dash because it refuses to operate process substitution right of a file substitution.

Explanations:

  • 2>&1 redirects stderr (file descriptor 2) to stdout (file descriptor 1).
  • | is the regular piping of stdout to the stdin of another command.
  • : is a shell builtin which does nothing (it is equivalent to true).
  • &> redirects both stdout and stderr outputs to a file.
  • >(your-command) is process substitution. It is replaced with a path to a special file, for instance: /proc/self/fd/6. This file is used as input file for the command your-command.

Note: A process trying to write to a closed file descriptor will get an EBADF (bad file descriptor) error which is more likely to cause abortion than trying to write to | true. The latter would cause an EPIPE (pipe) error, see Charles Duffy's comment.

loxaxs
  • 2,149
  • 23
  • 27
  • I wouldn't quite say "equivalent"; `>&-` *actually* closes the descriptor, and behavior is rather different (writes to a closed, and thus nonexistent, FD result in a different, more-likely-to-be-fatal error). – Charles Duffy Nov 06 '17 at 20:51
  • Compare `python -c 'print "hello"' >&-`, `python -c 'print "hello"' | true` and `python -c 'print "hello"' > /dev/null`. – loxaxs Nov 07 '17 at 14:52
  • 1
    `... | true` returns `EPIPE`, whereas `>&-` returns `EBADF` -- two completely separate errors. That the Python runtime doesn't distinguish between them usefully is neither here nor there. – Charles Duffy Nov 07 '17 at 15:29
2

It's also worth noting, that often times redirecting output is not really necessary. Many Unix and Linux programs accept a "silent flag", usually -n or -q, that suppresses any output and only returns a value on success or failure.

For example

grep foo bar.txt >/dev/null 2>&1
if [ $? -eq 0 ]; then
     do_something
fi

Can be rewritten as

grep -q foo bar.txt
if [ $? -eq 0 ]; then
     do_something
fi
Reverent Lapwing
  • 283
  • 2
  • 11
  • Checking `$?` unnecessarily is bad form, as opposed to `if grep -q foo bar.txt; then` -- it makes your code fragile, such that newly-added log lines can break your tests if someone doing such log instrumentation isn't cautious about where `$?` is expected to remain unchanged. – Charles Duffy Nov 07 '17 at 17:51
2

If /dev/null is too much to type, you could (as root) do something like:

ln -s /dev/null /n

Then you could just do:

program >/n 2>&1

But of course, scripts you write in this way won't be portable to other systems without setting up that symlink first.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
1

Ayman Hourieh's solution works well for one-off invocations of overly chatty programs. But if there's only a small set of commonly called programs for which you want to suppress output, consider silencing them by adding the following to your .bashrc file (or the equivalent, if you use another shell):

CHATTY_PROGRAMS=(okular firefox libreoffice kwrite)
for PROGRAM in "${CHATTY_PROGRAMS[@]}"
do
    printf -v eval_str '%q() { command %q "$@" &>/dev/null; }' "$PROGRAM" "$PROGRAM"
    eval "$eval_str"
done

This way you can continue to invoke programs using their usual names, but their stdout and stderr output will disappear into the bit bucket.

Note also that certain programs allow you to configure how much logging/debugging output they spew. For KDE applications, you can run kdebugdialog and selectively or globally disable debugging output.

Psychonaut
  • 859
  • 8
  • 22
  • 1
    Why use a string as if it were a list? If you're writing native bash (and using the `function` keyword means your code isn't *trying* to be portable; POSIX ), then you're guaranteed to have arrays; `chatty_programs=( okular firefox whatever ); for program in "${chatty_programs[@]}"; do`; that way your code doesn't depend on the current value of IFS. – Charles Duffy Oct 14 '17 at 12:52
  • 1
    I'd also consider letting the shell perform quoting for you: `printf -v eval_str '%q() { command %q "$@" &>/dev/null; }' "$program" "$program"; eval "$eval_str"` -- that way if someone borrows the idiom and runs it with input names they don't control, some joker creating a script named `$(rm -rf ~)` (yes, that's a valid filename -- be sure to use single-quotes if trying to create it) won't cause them a bad day. – Charles Duffy Oct 14 '17 at 12:54
  • @CharlesDuffy: You are right; thanks for the suggested improvements. I have revised my answer accordingly. – Psychonaut Nov 05 '17 at 10:53
  • +1. That said, re: variable naming convention, see http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html, fourth paragraph -- all-caps names are used for variables with meaning to POSIX-specified tools (the OS or shell), whereas other names are reserved for application namespace and guaranteed not to change behavior of POSIX-specified tools. Staying out of the all-caps is thus not only useful for avoiding unintentionally overwriting PATH and the like, but also avoiding unintentional changes to shell-internal variables yet-to-be-introduced. – Charles Duffy Nov 06 '17 at 20:48
0

Seems to me, that the most portable solution, and best answer, would be a macro on your terminal (PC).

That way, no matter what server you log in to, it will always be there.

If you happen to run Windows, you can get the desired outcome with AHK (google it, it's opensource) in two tiny lines of code. That can translate any string of keys into any other string of keys, in situ.

You type "ugly.sh >>NULL" and it will rewrite it as "ugly.sh 2>&1 > /dev/null" or what not.

Solutions for other platforms are somewhat more difficult. AppleScript can paste in keyboard presses, but can't be triggered that easily.

Maryam Jeddian
  • 261
  • 3
  • 4