What does 2>&1 mean here?

Before talking about redirections i have the feeling that you need to understand a basic thing:
Linux commands produce normal output and error output, and unix gives you the freedom to “redirect” each output to a separate “channel” , called file descriptors (fd).

Channel/fd 1 is used for std ouput and Channel/fd 2 is used for error output.

For example you can have a command to run like this :

$ command 1>output 2>errors #or more simple command >output 2>errors . A simple >output is a shortcut to 1>output

In above command nothing will be printed on your screen. Normal output will be sent to a local file called ‘output’ and errors will be sent to a local file called ‘errors’.

Now imagine yourself with two monitors, named tty0 and tty1.
You might distinguish output using something like

$ command 1>/dev/tty0 2>/dev/tty1

In this situation normal output of the command goes to channel 1 = tty0 and errors goes to channel 2 = tty1.

When you ommit redirections and you run a command by your shell prompt, channel 1 and channel 2 are both redirected to your one and only screen (tty0).

So by just running in your shell

$ command

is by default equivalent to

$ command 1>/dev/tt0 2>/dev/tt0

When we have a variable assignment (like your example) then the game is a bit different.
Shell creates a temp place (or a variable space if you prefer) to hold the normal output produced by the command, but the error output is not driven to the variable by default.

So for a variable assignment like this one

variable=$(command) 

equals somehow to:

command 1>$variable 2>/dev/tt0    #this is not a valid syntax , it is just an example to demonstrate how different ouputs are handled by default.

Error output keeps going to tty0, your screen, unless you explicitly redirect error output to somewhere else like 2>file (send errors to a file) or 2>&1 = sent error output to the same location that normal output goes => variable.

Consider these tests:

echo "hello world" >hello.txt 
#we create a simple file. Channel number is not given but is considered to be 1 by defauly, so this is equivalent to echo "..." 1>hello.txt 
ls -all
> drwx------    2 9925691 root   4096 Dec 13 01:29 .
> drwxr-xr-x 2802 root    root 253952 Dec 13 01:29 ..
> -rw-r--r--    1 9925691 root     12 Dec 13 01:29 hello.txt

a=$(ls -all hello.txt) #variable assignment ignoring the error output
echo "Lets print the contents of variable 'a' : $a"
> Lets print the contents of variable 'a' : -rw-r--r-- 1 9925691 root 12 Dec 13 01:31 hello.txt

echo "one more test"
b=$(ls -all helo.txt) #there is no file helo.txt so this will produce an error
echo "variable 'b' contains: $b"
> one more test
> variable 'b' contains:  #nothing is printed in normal output &1 so the variable is null
> ls: cannot access 'helo.txt': No such file or directory #this error is printed directly to tty0, is not stored in variable "$a" and thus can not be used later on from your scripts.

echo "another test'
c=$(ls -all helo.txt 2>&1)
echo "variable 'c' contains: $c"
> another test
> variable 'c' contains: ls: cannot access 'helo.txt': No such file or directory #Variable $c contains the error output of the command ls.
> #nothing is printed on your screen directly. is all stored in variable "$c"

Leave a Comment