Linux Bash: Language Basics

I will not write all story here but people were using Teleprinter (Teletypewriter, Teletype, TTY) from 1830s and 1840s. As seen in the following pictures, it was an electromechanical device used for communicating text over telegraph lines etc. There wasn't any monitor, output was written in a paper. Some models were creating punched tape for data storage (either from typed input or from data received from a remote source) and read back such tape for local printing or transmission.

Nowadays, we use computers with monitor and operating system but Linux still uses TTY concept under the hood 🙂

You can find some diagrams below relation with Terminal Emulator and TTY

Teletypewriter(Teletype, Teleprinter or TTY)
A restored 1930s Teletype is now a Linux TTY
A Teletype Model 32 ASR used for Telex service
Video terminals like the DEC VT-100 (1978) made teletypes obsolete as computer I/O devices
Terminal Emulator (Pseudo type writer or PTY)
Each Terminal Emulator window attached to separate TTY as shown in the above screenshot.

stdin, stdout and stderr

Linux attaches stdin, stdout and stderr streams for each program by default in the Linux terminal. These streams carry text as data. So, streams are used to pass data into programs and to get data out of them.

Execution Life cycle of one program in Linux

Execution Life cycle of piped two programs in Linux

Execution Life cycle of piped three programs in Linux

In Linux, almost all the streams are treated as if they were files. Just like you can read/write a file, you can read/write a data from these streams.

stdin: Stands for standard input. It takes text as input.
stdout: Stands for standard output. The text output of a command is stored in the stdout stream.
stderr: Stands for standard error. Whenever a command faces an error, the error message is stored in this stream.

Each stream has file descriptor ID as below

  • stdin – /dev/stdin or /dev/fd/0
  • stdout – /dev/stdout or /dev/fd/1
  • stderr – /dev/stderr or /dev/fd/2

Stdin example

read command require input from the keyboard.

When no argument is provided to read command, the entire line is assigned to the REPLY variable. So, we can print REPLY variable in terminal as below.

$ read
Hello World

$ echo $REPLY

Hello World

Stdout example

Output of echo command is written to terminal or stdout

$ echo "Hello World"

Hello World

Piping Streams

The | sign is responsible for piping the stdout stream of a command to the stdin stream of next command.

The |& sign is responsible for piping both stdout and stderr streams of a command to the stdin stream of next command.

Piping stream is a form of redirection. It only redirect stdin, stdout and stderr streams.

$ echo "Hello World" | grep Hello

Hello World

The output of echo command is written in the stdout stream, then the piping redirects the content of stdout to stdin for the grep command. That's how grep command knows what content to perform the operation on.

If you want to pipe both the stdout and stderr to the next command, then use the I& instead of I

$ anything |& cat

zsh: command not found: anything

Redirecting Streams

The > sign is responsible for redirecting the stdout stream of a command to a file stream.

The >> sign is responsible for appending the stdout stream of a command to a file stream.

The < sign is responsible for redirecting the file stream to a stdin stream of a command.

The << sign is responsible for redirecting the multi-line string to a stdin stream of a command. It is also known as here-document.

The <<< sign is responsible for redirecting the single string to a stdin stream of a command. It is also known as here-string.

The >& sign is responsible for redirecting and merging both stdout and stderr streams of a command to the file stream.

Redirecting stream is similar to Piping stream but it is used for file stream to stdin or stdout streams.

Redirecting stdout stream of a command to file stream

$ echo "Hello World" > hello.txt

or

$ echo "Hello World" 1> hello.txt

Redirecting stderr stream to file stream

$ something 2> error.txt

/dev/null is a special file which ignores anything put into it.

$ something 2> /dev/null

Appending stdout stream of a command to file stream

$ echo "How is the weather today?" >> hello.txt

or

$ echo "How is the weather today?" 1>> hello.txt

Redirecting file stream to stdin stream of a command

$ cat < hello.txt

Hello World

or

$ echo "Hello World" | cat

Hello World

Redirecting file stream to stdin stream of a command as parameter

$ cat > input.txt <<EOL
kenan
kenanhancer@gmail.com
EOL
$ cat > greeting.sh <<EOL
#!/bin/bash

echo "Enter name"
read name

echo "Enter email"
read email

echo "Your name is $name and email is $email"
EOL
$ . ./greeting.sh < input.txt

Enter name
Enter email
Your name is kenan and email is kenanhancer@gmail.com

Redirecting file stream to stdin stream of a command as parameter and redirecting stdout stream of command to file stream.

$ . ./greeting.sh < input.txt > greetingOutput.txt
$ cat greetingOutput.txt

Enter name
Enter email
Your name is kenan and email is kenanhancer@gmail.com

Redirecting stderr and stdout streams to separate file streams

$ echo “hello world” 1> output.txt 2> debug.txt

Some examples

$ ls -l > output.txt
$ wc -l countries.txt > output.txt
$ ls -l >> output.txt
$ wc -l < countries.txt
$ wc -l < countries.txt > output.txt
$ ls -l blabla 2> error.log
$ ls -l blabla >& outputOrError.txt

or

Redirecting stdout stream to file stream and stderr stream to file stream. We redirect to a file stream first then redirect the error stream.

$ ls -l blabla > outputOrError.txt 2>&1
$ ls | head -3 | tail -1 > output.txt

Command Substitution

Command substitution is shown as $() sign.

$ NOW=$(date)
$ echo $NOW

Sun 19 Jun 2022 16:57:16 BST

or

$ echo $(date)

Sun 19 Jun 2022 16:57:16 BST
$ echo "Date is $(date)"

Date is Sun 19 Jun 2022 16:58:02 BST
$ cat <<< "Date is $(date)"

Date is Sun 19 Jun 2022 16:58:02 BST
$ cat <<< $(echo "Date is $(date)")

Date is Sun 19 Jun 2022 16:58:02 BST
$ echo "Date is $(date)" | cat

Date is Sun 19 Jun 2022 16:58:02 BST

Process Substitution

Process substitution is shown as <() sign. Process Substitution writes output in a file and returns that file name.

$ cat <(date)

Sun 19 Jun 2022 16:58:02 BST
$ cat < <(date)

Sun 19 Jun 2022 16:58:02 BST
$ date | cat

Sun 19 Jun 2022 16:58:02 BST
$ echo $(date) | cat

Sun 19 Jun 2022 16:58:02 BST

Leave a Reply