# Redirections
#
# I/O in the shell is a complex topic, but a very important one.
# Input and output can be:
#   - anything a file descriptor can point to (file, socket, terminal,etc.)
#   - command line arguments
#   - environment variables
#
# FD are like pointers to places you can read from or write to, such as
# files, pipes, devices, sockets, and terminals.
# FDs are always referenced by non-negative integers.
# Each process starts with 3 open FDs: 0 (stdin), 1 (stdout) and 2 (stderr)
# In an interactive shell, this looks like:
#
#                +-------------+
#   keyboard ----| 0  shell  1 |--+-- display
#                |           2 |--|
#                +-------------+
#
# Redirection is the way you can tell a command to read its input or write
# its output to a particular FD.
# It can also be used to open, close, and duplicate FDs.
#
# For example, when you run: $ ls >listing.txt 2>/dev/null
# the shell does this:
#
#                +-------------+
#   keyboard ----| 0  shell  1 |--+-- display
#                |           2 |--|
#                +------+------+
#                       |
#                +------+------+
#   keyboard ----| 0   ls    1 |---- listing.txt
#                |           2 |---- /dev/null
#                +-------------+
#
# Bash handles several filenames specially when they are used in
# redirection:
#
# /dev/stdin             FD 0
# /dev/stdout            FD 1
# /dev/stderr            FD 2
# /dev/fd/n              FD n
# /dev/tcp/host/port     TCP socket to host:port
# /dev/udp/host/port     UDP socket to host:port
#
#
# ==[ Redirecting input
#
# Syntax: [n]<word
#
# It opens the file whose name results from expanding 'word' for reading
# and redirects it to FD 'n' or 0 if 'n' is not specified.
#
# Example: $ cat < foo
# 
# 
# ==[ Redirecting output
#
# Syntax: [n]>word
#
# It opens the file whose name results from expanding 'word' for writing
# and redirects FD 'n' or 1 if 'n' is not specified.
#
# Example: printf "%s\n%s\n" hello bye > foo
# Example: rmdir xyz 2> errors (assuming directory 'xyz' doesn't exist)
#
# You can apply multiple redirections: ls a b > out.log 2> errors.log
# (Make sure 'a' exists and 'b' does not exist)
# Warning! Rediretions are applied in order
#
# Consider these two cases:
#   (1) ls >files.txt 2>&1
#   (2) ls 2>&1 >files.txt
#
# They do very different things!
#
#
# ==[ Appending redirected output
#
# Syntax: [n]>>word
#
# It opens the file whose name results from expanding 'word' for appending
# and redirects FD 'n' or 1 if 'n' is not specified
#
# Example: echo "test" >> foo
#
#
# ==[ Redirecting stdout and stderr
#
# Syntax: &>word (preferred) or >&word
#
# It is equivalent to: >word 2>&1
#
# For appending redirection use: &>>word
#
# It is equivalent to >>word 2>&1
#
# Use with caution because it is not portable to Bourne shell.
#
#
# ==[ Opening FDs for reading and writing
#
# Syntax: [n]<>word
#
# Opens 'word' for both reading and writing on FD 'n'.
# 'n' is 0 if not specified.
# 'word' is created if not existing.
#
# Common use is through the 'exec' command, which applies the redirection
# for the current process.
# Example:
#
#   exec 3<>/dev/tcp/www.host.com/21
#
# Opens a TCP socket to www.host.com:21.
# You can send and receive by writing and sending to FD 3.
#
#
# ==[ Duplicating FDs
#
# Syntax: [n]<&word (with word expanding to digits)
#         [n]>&word
#
# Used to duplicate input FDs.
# 1st case: 'n' is now a copy of the FD specified by 'word'.
# 2nd case: 'word' is now a copy of the FD specified by 'n'.
# If 'n' is omitted, it redirects to stdin or stdout, respectively.
#
#
# ==[ Moving FDs
#
# Moving is duplication + closing the FD.
#
# Syntax: [n]<&word-
#         [n]>&word-
#         
# 1st case: moves FD 'word' to 'n' (0 if not specified) and closes 'word".
# 2nd case: moves FD 'n' (1 if not specified) to 'word' and closes 'n'.
#
#
# ==[ exec
#
# 'exec' replaces the current shell by another program.
# It can also be used to do redirections that apply to the process
# (typically, to all commands in a script).
#
# Example: exec >> "logfile.txt" 2>&1
#
# Typical usage:
#
#   exec <file      # redirects stdin
#   exec >file      # redirects stdout
#   exec 3<file     # opens 'file' for reading
#   exec 3>file     # opens FD 3 for writing
#   exec 3>&-       # closes FD 3
#   exec 3<>file    # opens file for reading and writing
#
# Example
# -------
# exec 3>&1 >foo.log; echo one; echo two; exec 1>&3 3>&-
#
# Example
# -------
# exec 3>myfile.txt; echo hello >&3; exec 3>&-
#
# Example
# -------
# exec 5<>/dev/tcp/ifconfig.me/80
# echo "GET /ip HTTP/1.1
# Host: ifconfig.me
# " >&5
# cat <&5
# exec 5>&-
#
# We will return to these examples later in the course.
