bhylu.com

Advertisements

Bash Redirection

Keep standard output and diagnostics in separate files.

How it works

A process normally has standard input, standard output and standard error. Bash redirection connects those streams to files or other descriptors before starting the command. Order matters when duplicating descriptors. A separate diagnostic stream lets a caller consume results without accidentally treating an error message as a data record. Choose append or replacement deliberately.

Run the code

Reviewed with Git for Windows Bash 5.2.37. Open Git Bash, save the download with LF line endings in a separate learning folder, check it with bash -n lesson-name.sh, then run bash lesson-name.sh using the actual filename. Bash 4 or newer is required for the full course. Linux-only notes identify unavailable tools or POSIX behaviour. There is no Bash browser runner; Apache and MySQL are not required.

This complete example was executed in the stated local review environment.

The complete source creates a fresh private temporary workspace and checks its physical path before cleanup. All file fixtures belong to that workspace; do not remove the guards or point it at existing documents.

Download complete source

Example

redirection.sh

#!/usr/bin/env bash
set -u
set -o pipefail
export LC_ALL=C

# Own a new directory; verify physical paths before cleanup.
parent=$(cd -- "${TMPDIR:-/tmp}" && pwd -P) || exit 1
work=$(mktemp -d "$parent/bhylu-bash.XXXXXX") || exit 1
work=$(cd -- "$work" && pwd -P) || exit 1
case "$work" in "$parent"/bhylu-bash.??????) ;; *) exit 1 ;; esac
cleanup() {
    cd -- "$parent" || return 1
    [[ -d $work && ! -L $work ]] || return 1
    [[ $(cd -- "$work" && pwd -P) == "$work" ]] || return 1
    case "$work" in "$parent"/bhylu-bash.??????) rm -r -- "$work" ;; *) return 1 ;; esac
}
trap cleanup EXIT
cd -- "$work" || exit 1

{ printf "north,8\n"; printf "note: synthetic data\n" >&2; } > rows.csv 2> notes.txt
[[ $(cat rows.csv) == "north,8" ]] || exit 1
[[ $(cat notes.txt) == "note: synthetic data" ]] || exit 1
printf "Data and diagnostic streams separated\n"

Focus on the lesson commands

This excerpt omits temporary-workspace setup and cleanup. Use the complete source above to run the example.

Command excerpt

{ printf "north,8\n"; printf "note: synthetic data\n" >&2; } > rows.csv 2> notes.txt
[[ $(cat rows.csv) == "north,8" ]] || exit 1
[[ $(cat notes.txt) == "note: synthetic data" ]] || exit 1
printf "Data and diagnostic streams separated\n"

Expected result

Data and diagnostic streams separated

The compound command supplies two streams and the shell captures each separately. Both expected contents are checked before a success message is printed. The fixture files are owned by this temporary lab. Using 2>&1 would merge diagnostics into the result, which may be appropriate for a log but not for a machine-readable table.

Primary technical reference: Bash documentation.