This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the bash category.
Last Updated: 2023-03-28
echo hi > file - changes file descriptor 1 (STDOUT) to file. Same as
Therefore, if you do a command that also has errors as well as normal output, it won't appear in the file. Here's proof:
# Running ls a real dir (tmp) and a non-existent one $ ls /tmp/ doesnotexist > file # In the terminal, we get an error about the non-existent directory, but nothing # about /tmp => ls doesnotexist: No such file or directory # But when we look inside the file, it has the normal non-error output (but no mention of the error) cat file filea filb
cat < file - changes file descriptor 0 to file. I.e. takes input from there
And lastly, pipe wires STDOUT of one command to STDIN of others
echo foo | cat
2>without any ampersand.
ls /tmp doesnotexist 2> errfile. This puts the STDERR in errfile (and prevents it being printed on the terminal)
# Send errors to one file and normal output to another $ ls /tmp/ doesnotexist 2> errfile 1> file # Prove it worked $ cat errfile ls: doesnotexist: No such file or directory $ cat file realfile.docx anotherrealfile.pdf
The following code combines STDERR into STDOUT. Now the pipe can read from STDERR as well (probably not what you want though!) However watch out - pipes can therefore swallow errors silently...
ls /tmp/ doesnotexist 2>&1 | cat
2>&1 - something written on STDERR will go to whatever 1 references
command 2>&1 > file is not the same as
command >file 2>&1
Why the difference? The key is that the redirection (kinda like C pointers -
reminder: & deferencing) just gives a reference to its current value. So in
the first command, stderr is redirected to whatever fd1 is at the time, which,
/dev/ttys006 as shown by
lsof when you ask it what is connected to the
current process of the shell (
$ lsof -p $$ zsh 54371 jack 0u CHR 16,6 0t1686916 5705 /dev/ttys006 zsh 54371 jack 1u CHR 16,6 0t1686916 5705 /dev/ttys006 zsh 54371 jack 2u CHR 16,6 0t1686916 5705 /dev/ttys006 zsh 54371 jack 10u CHR 16,6 0t115249 5705 /dev/ttys006 # CHR – Character special file
Shell commands have many "outputs" - aside from what's sent to fd1 & fd2, there is a return code which can be used in logic, and a process id (say if it was backgrounded).