2

Could someone help me under stand the condition ls /etc/*release 1>/dev/null 2>&1 that's contained in the code:

    if ls /etc/*release 1>/dev/null 2>&1; then
       echo "<h2>System release info</h2>"
       echo "<pre>"
       for i in /etc/*release; do

           # Since we can't be sure of the
           # length of the file, only
           # display the first line.

           head -n 1 $i
       done
       uname -orp
       echo "</pre>"
    fi

I pretty much don't understand any of that line but specifically what I wanted to know was:

  1. Why dose it not have to use the 'test' syntax i.e. [ expression ]?
  2. The spacing in the condition also confuses, is 1>/dev/null a variable in the ls statement?
  3. what is 2>&1?

I understand the purpose of this statement, which is; if there exists a file with release in it's name under the /etc/ directory the statement will continue, I just don't understand how this achieves this.

Thanks for you help

Chris
  • 362
  • 6
  • 16

2 Answers2

4

[ isn't a special character, it's a command (/bin/[ or /usr/bin/[, usually a link to test). That means

if [ ...
if test ...

are the same. For this to work, test ignores ] as last argument if it's being called [.

if simply responds to the exit code of the command it invokes. An exit code of 0 means success or "true".

1>/dev/null 2>&1 redirects stdout (1) to the device /dev/null and then stderr (2) to stdout which means the command can't display and output or errors on the terminal.

Since stdout isn't a normal file or device, you have to use >& for the redirection.

At first glance, one would think that if [ -e /etc/*release ] would be a better solution but test -e doesn't work with patterns.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • Thanks! Can you refer to stdout and stderr with the numbers in any part of the shell script or does it only work in conditional statements? – Chris Feb 26 '15 at 15:26
  • In the case of `ls /etc/*release 1>/dev/null 2>&1` are they simply testing `if 1`? – jcbermu Feb 26 '15 at 15:26
  • @jcbermu I believe your right. From Aarons explanation of redirection I understand this simply redirects the exit status of `ls` to basically say `if [ stderr -eq 0 ]`, i.e. there is a listing in /etc/ with the phrase release in it. – Chris Feb 26 '15 at 15:43
  • @Chriso: stderr is not related to the exit code. Exit code is in `$?` after a command was executed. `if [ stderr -eq 0 ]` is always false: `stderr` is no variable name (missing `$`). And you can't compare a file descriptor with a number. – Aaron Digulla Feb 27 '15 at 16:43
0

The test programm just evaluate its arguments and return a code 0 or 1 to tell whether it was true or not.

But you can use any shell commands/function with a if. It will do the then part if the return code ($?) was 0. So, here, we look if ls return 0 (a file matched), or not.

So, in the end, it's equivalent to write if [ -e /etc/*release ] ; then, which is more "shell-liked".

The last two statements 1>/dev/null and 2>&1 are just here to avoid displaying the output of the ls

  • 1>/dev/null redirect stdout to /dev/null, so the standard out is not shown
  • 2>&1 redirect stderr to stdout. Here, stdout is redirected to /dev/null, so everything is redirected to /dev/null
Corentin Peuvrel
  • 310
  • 1
  • 2
  • 9