Bash Index : E - The 'E' Bash commands : description, flags and examples

exit

Usage :

exit n

Example :

When used within a function, will exit exit the script or the function ?

#!/usr/bin/env bash

getOutOfHere() {
	echo 'So long, and thanks for all the fish!'
	exit
	}

echo 'BEFORE'
getOutOfHere
echo 'AFTER'
BEFORE
So long, and thanks for all the fish!

exit ends the script.

e2fsck, fsck.ext3, fsck.msdos

Usage :

File System Check : check and repair file systems of the ext2 / ext3 / ext4 family.
These commands are synonymous.

This command MUSTN'T be used on mounted filesystems.

Flags :

Flag Usage
-a automatically repair the file system without any questions (use this option with caution)
-c check disk for new bad blocks, and append them to the list of bad blocks
-f force checking even if the file system seems clean.
-n Assume an answer of no to all questions. Warn only, don't write anything to the disk. Conflicts with -p and -y.
-p repair automatically without asking : fix any problem that can be safely fixed without human intervention.
-v verbose mode
-w write changes to disk immediately (for fsck.msdos only)
-y Assume an answer of yes to all questions. Conflicts with -n and -p.

Exit codes :

Bit Usage
0 No error
1 All errors have been corrected
2 All errors have been corrected but system should be rebooted
4 Some errors left uncorrected
8 Operational error
16 Usage or syntax error
32 Program cancelled by user request
64 (unused)
128 Shared library error

Example :

umount /dev/sdb1 && fsck.ext3 -pv /dev/sdb1

export

Usage :

When a program is invoked it is given an array of strings called the environment. This is a list of name-value pairs, of the form name=value. On invocation, the shell scans its own environment and creates a parameter for each name found, automatically marking it for export to child processes. Executed commands inherit the environment.
The export and declare -x commands allow parameters and functions to be added to and deleted from the environment. If the value of a parameter in the environment is modified, the new value becomes part of the environment, replacing the old. The environment inherited by any executed command consists of the shell's initial environment, whose values may be modified in the shell, less any pairs removed by the unset command, plus any additions via the export and declare -x commands.
When bash invokes an external command, the variable _ is set to the full file name of the command and passed to that command in its environment.

These 2 constructs are equivalent :

Flags :

Flag Usage
-f name name being exported is a function
-n name unexport the variable name
-p print all exported variables

Example :

An example is worth 1000 words :

$foo='Hello, World'; echo $foo

Hello, World


$bar='Goodbye'; export foo; bash
bash-3.2$echo $foo

Hello, World

bash-3.2$echo $bar

(nothing)


bash-3.2$exit
$export -n foo; bash
bash-3.2$echo $foo

(nothing)

bash-3.2$exit

exec

Usage :

execute commands and open, close, or copy file descriptors

Example :

Playing with file descriptors :

Open readFile as file descriptor 3 for reading :
exec 3< readFile
Open writeFile as file descriptor 4 for writing (examples) :
exec 4> writeFile
Make file descriptor 5 a copy of file descriptor 0 :
exec 5<&0
Close file descriptor 3 :
exec 3<&-

File descriptors 0, 1 and 2 are "reserved". You can still use them, but don't forget you're not the only one using them (details)

The exec > /path/to/logFile 2>&1 construct (source, use with care in one-liners) :

This is a trick so that stdout and stderr are redirected to /path/to/logFile for ALL commands of a script. Let's experiment this :

#!/usr/bin/env bash

logFile=$(mktemp --tmpdir tmp.logFile.XXXXXXXX)
>"$logFile"		# purge the log file of previous tests

exec 2>> "$logFile"	# redirect stderr to log file
ls .			# list the current directory contents in the shell window
ls aFileThatIsNotHere	# the error message is appended to the log file but not shown in the shell window

exec &>> "$logFile"	# redirecting stdout and stderr to log file
ls ..			# list the parent directory contents in the log file
ls aFileThatIsNotHere	# the error message is appended to the log file but not shown in the shell window
  • exec > /path/to/logFile 2>&1 can be shortened to exec &> /path/to/logFile
  • In the snippet above, I use double redirection >> because I don't want successive calls to exec from the same script to overwrite the log file. In the "real word", calling exec only once should suffice and single redirection (>) should be enough, unless you want to append to the same log file forever . Check it :
    outFile='./outFile'; exec 4>$outFile; echo 'hello' >&4; echo 'world' >&4; cat $outFile; rm $outFile
    hello
    world
    outFile='./outFile'; exec 4>$outFile; echo 'hello' >&4; exec 4>$outFile; echo 'world' >&4; cat $outFile; rm $outFile
    world
    outFile='./outFile'; echo 'HELLO' >$outFile; exec 4>$outFile; echo 'hello' >&4; echo 'world' >&4; cat $outFile; rm $outFile
    hello
    world
    outFile='./outFile'; exec 4>$outFile; echo 'hello' >&4; exec 4>>$outFile; echo 'world' >&4; cat $outFile; rm $outFile
    hello
    world
    outFile='./outFile'; echo 'HELLO' >$outFile; exec 4>>$outFile; echo 'hello' >&4; echo 'world' >&4; cat $outFile; rm $outFile
    HELLO
    hello
    world

Some restrictions apply to one-liners :

The exec &> /path/to/logFile construct is extremely convenient but should be used with care in one-liners. Indeed, such commands may affect the current shell :

exec &>/dev/null; echo 'hello world'; echo 'anybody there ?'
This redirects the default file descriptors STDOUT and STDERR to /dev/null, including for the current session : this will display nothing forever and you've just f*cked up your current shell session
(exec &>/dev/null; echo 'hello world'); echo 'anybody there ?'
This will display anybody there ? only : thanks to the (), the /dev/null redirect is only effective within a subshell process. You current shell session is safe

eval

Execute arguments as a shell command. Let's see what this means with examples :
myCommand='ls -l'; $myCommand
This effectively lists files.
myCommand='ls -l | less'; $myCommand
ls: cannot access |: No such file or directory
ls: cannot access less: No such file or directory
This fails because ls tries to list files named | and less instead of considering these as the continuation of the command. ls needs to be taught that this is a whole command.
myCommand='ls -l | less'; eval "$myCommand"
Works like a charm

Quotes or not around the "evaluated" command ?

touch "withoutSpace" "with space"; ls -l withoutSpace with space
ls: cannot access with: No such file or directory
ls: cannot access space: No such file or directory
-rw-r----- 1 bob users 0 Sep  3 15:23 withoutSpace
touch "withoutSpace" "with space"; ls -l withoutSpace "with space"
-rw-r----- 1 bob users 0 Sep  3 15:23 withoutSpace
-rw-r----- 1 bob users 0 Sep  3 15:23 with space
touch "withoutSpace" "with space"; command='ls -l withoutSpace "with space"'; $command
ls: cannot access "with: No such file or directory
ls: cannot access space": No such file or directory
-rw-r----- 1 bob users 0 Sep  3 15:24 withoutSpace
touch "withoutSpace" "with space"; command='ls -l withoutSpace "with space"'; eval $command
-rw-r----- 1 bob users 0 Sep  3 15:24 withoutSpace
-rw-r----- 1 bob users 0 Sep  3 15:24 with space
touch "withoutSpace" "with space"; command='ls -l withoutSpace "with space"'; eval "$command"
-rw-r----- 1 bob users 0 Sep  3 15:25 withoutSpace
-rw-r----- 1 bob users 0 Sep  3 15:25 with space

doesn't seem to make a difference

echo

Usage :

Display message on screen, writes each given string to standard output, with a space between each and a newline after the last one.

Flags :

Flag Usage
-e enable interpretation of backslash-escaped characters. the output string must be quoted (either single or double).
-n Do not output the trailing newline.