input output, file, pipe, redirections and parameters
Fuck this cryptic syntax.
§ Redirection
example
#! /usr/bin/bash
echo_to_err() { printf "%s\n" "$*" >&2; }
echo "to stdout"
echo_to_err "to stderr"
shut the fuck up
Redirect everything to black hole. note that you need to redirect stdout
to
file first, then redirect stderr
to stdout
[^order]
$ ./example > /dev/null 2>&1
ordering of redirect
in the last example you need to first redirect stdout
to file then stderr
to
stdout
. this post
nicely explain why the ordering is like this.
In a nutshell: >
is an asignment, not an arrow! e.g. with > file
you asign
file (rvalue) to 1
(lvalue), NOT point 1 to file.
> /dev/null # 1 becomes `file`
2>&1 # 2 becomes value of 1 i.e. `file`
# & is like $, marking a variable)
symbols & MISC
< input redirection
<< input redirection, here document
<<< input redirection, here string
> output redirect, overwrite if targeting file
>> output redirect, append if targeting file
redirect flle to program stdin:
wc < file
(duplicate) the stream
command | tee <file>
:
Keep tty output and write to file (i.e. , do not redirect). In the following
example both “to stdout” and “to stderr” are printed to tty “to stdout” is
written to log.txt
$ ./example | tee log.txt
redirect stderr to stdout
use 2>&1
$ ./example 2>&1 | tee log.txt
file descriptors:
0 for stdout
, 1 for stdin
, 2 for stderr
char devices
/dev/null
- black hole, swallows whatever you give it without side effect. Useful for silencing program output. Unlike this provides no output if you read it.
/dev/zero
- continuous stream of NULL, can be used to wipe a storage device with
dd
(if you know what you are doing…) /proc/<PID>/fd/
- file descriptors of process
<PID>
for normally both0
and1
are linked to/dev/tty*
but redirecting things to these FDs may not work as you expected…. /dev/stdin -> /proc/self/fd/0
/dev/stdout -> /proc/self/fd/1
/dev/stderr -> /proc/self/fd/2
- duplicated fds for the current process’s stdio
here string
$ COMMAND <<< $THING
Is (effectively) equivalent to
echo $THING | COMMAND
Where $THING
is expanded and fed to stdin of COMMAND. However the later
echo-pipe example essentially creates two processes (echo and COMMAND) and
redirect one’s stdout
to another’s stdin
.
here document
$ COMMAND << EOF
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo
ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis
parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec,
pellentesque eu,
EOF
§ Pipe & Socket & term
§ Parameters
NOTE: this one is not about bash scripting, i.e. I won’t include stuffs like “how can I parse commandline options”
double minus --
marks the end of command options. After which only positional arguments are
accecpted. For example if you have a file called -v
, cat -v
won’t work
because -v
is treated as an argument to cat
. Instead do cat -- -v
single minus -
It depends of commands. But most intriguingly: use with a pipe, to use a
program’s output as another’s parameter.
$ echo "hello" | rm -
equals
$ rm hello
or
$ rm $(echo "hello")
Another useful example is
$ pacman -Qtdq | sudo pacman -Rns -
which finds and kill the orphans (evil pun
intended)
§ Privilege
redirects are performed by the shell. Sudo gives privelege to the annoted program, not to the shell. e.g. the following won’t work even with sudo
$ sudo echo 0 > /proc/sys/kernel/sysrq
warning: An error occurred while redirecting file '/proc/sys/kernel/sysrq'
open: Permission denied
wordaround with tee:
$ echo 0 | sudo tee /proc/sys/kernel/sysrq
refs
- here string: https://tldp.org/LDP/abs/html/x17837.html
- more on how here string works vs. pipe: https://unix.stackexchange.com/a/219805
- bash redirections, GNU: https://www.gnu.org/software/bash/manual/html_node/Redirections.html