Bash ==== .. toctree:: variables.rst conditionals.rst jobs.rst forking.rst examples.rst arrays.rst Online GNU Docs https://www.gnu.org/software/bash/manual/html_node/index.html#SEC_Contents Redirections ------------ Online GNU Docs: Redirections: https://www.gnu.org/software/bash/manual/html_node/Redirections.html each process starts with three streams: * stdin, fd=0 * stdout, fd=1 * stderr, fd=2 .. code-block:: bash # redirect std err, to prevent it from printing on the console or other files sudo apt update 2>/dev/null # redirect stdout and std err to separate files ls -la 1>ls_stdout 2>ls_stderr # invalid option to demonstrate the error stream ls -! 1>ls_stdout 2>ls_stderr # redirect stdout to a file, and stderr to stdout ls -la &> ls_out # which is equivalent to ls -la 1>ls_out 2>&1 # append-redirect stdout to a file, and stderr to stdout ls -la &>> ls_out # Redirect stdout to stdout (FD 1) echo "hello there" 1>&1 # Redirect stdout to stderr (FD 2) echo "hello there" 1>&2 # Redirect stderr to stdout echo "hello there" 2>&1 Bash Pipelines -------------- .. code-block:: bash # cmd1 | cmd2 groups | sed 's/\s\+/,/g' * the ``|`` to pipe **stdout** to **stdin** of next cmd * the ``|&`` to redirect **stderr** to **stdout** before piping to **stdin** * the ``|&`` is equivalent to to ``cmd1 2&>1 | cmd2`` Another idea is to use ``xargs`` build and execute command lines from standard input .. code-block:: bash # generate a sequence of 5 numbers, and build arguments for the echo command seq 0 5 | xargs echo # generate a compact listing of all users on the System cut -d: -f1 < /etc/passwd | sort | xargs echo # pipline over SSH for a series of hosts for k in thinkpad uraspi znode; do ssh $k "mkdir /bits/zkeys && mv /bits/vpnkeys /bits/zkeys/pki"; done Bash Command Lists ------------------ .. code-block:: bash # execute A, then execute B if A was successful echo A && echo B # execute B only if A fails echo A || echo B # execute A, then Execute B echo A; echo B # execute A, B and C in parallel echo A & echo B & echo C & Bash special parameters (Special Variables) ------------------------------------------- GNU Man Pages: Special Parameters https://www.gnu.org/software/bash/manual/bash.html#Special-Parameters ``$$`` **own process ID** .. code-block:: bash echo $$ MYPID=$$ echo $MYPID ``$!`` **the pid of the last background-ed process** .. code-block:: bash # run in the background tail -f /var/log/dmesg & bgtail_pid=$! # better store the PID before it flies echo $bgtail_pid # and then later use it, probably by sending a signal kill -s SIGQUIT $bgtail_pid ``$#`` **the count of positional args starting of a function from 1** .. code-block:: bash a_test_func () { echo $# } a_test_func hello world "a quoted hello world, making a total of 3 args" ``$*`` and ``$@`` **expansion of positional arguments, starting from 1** There are subtle differences between the two: * ``"$*"`` is equivalent to ``"$1 $2 ..."`` * ``"$@"`` is equivalent to ``"$1" "$2" ...`` .. code-block:: bash a_test_func () { echo got $# args: "$*" echo alt syntax: "$@" } a_test_func hello world "a quoted hello world, making a total of 3 args" ``$?`` **the exit status of the most recent foreground pipeline** .. code-block:: bash last_status=$? # better store it right away echo $last_status # then do something with it ``$-`` **Bash flags** .. code-block:: bash echo $- # expands to the current bash flags by the set built in command ``$1`` **Position Parameters** .. code-block:: bash echo $0 # expands to the name of the shell, or the shell script invoked echo $1 # the first positional argument echo $2 # the second positional argument Bash Builtins ------------- The **declare** built-int .. code-block:: bash declare --help declare -F # print declared bash function names declare -f # print declared bash function names and definitions The **set** build-in, and Bash flags .. code-block:: bash set --help echo $- # expands to the current bash flags by the set built in command set -e # exit upon non-zero exit code echo $- # the e flag should now be visible among the default flags set +e # undo the e flag generate error on expanding unbound variables set -u Bash Loops and Foreach ---------------------- .. code-block:: bash # explicit positional parameters for k in bananas apples oranges; do echo $k; done # expanding a list of tokens xlang="C Python Bash Javascript" for k in $xlang; do echo "I love $k"; done # expanding a function that products a lis of tokens for k in $(echo C Python Bash Javascript); do echo "I love $k"; done # looping over arrays xt=( a b c d ) for item in ${xt[@]}; do echo $item; done path_tokens=( $( echo "$PATH" | tr ":" " " ) ) for item in ${path_tokens[@]}; do echo $item; done Bash Tokenization and Splitting ------------------------------- The Internal Field Separator Variable ``$IFS`` can be used to determine the splitting character .. code-block:: bash DEFAULT_IFS=$IFS langs="python;javascript;ruby" IFS=";"; for k in $langs; do echo "$k"; done # Then change it to split the $PATH string IFS=":"; for p in $PATH; do echo "$p"; done IFS=$DEFAULT_IFS # or simply, to go back to the shell default unset IFS Another way is to use ``tr ":" "\n"`` to replace characters in a string or a stream .. code-block:: bash langs="python;javascript;ruby" for k in $(echo $langs | tr ";" " "); do echo "$k"; done # Then change it to split the $PATH string for p in $(echo $PATH | tr ":" " "); do echo "$p"; done