Linux & Shell Tips and Tricks
Table Of Contents
This is a collection of my favorite Tips and Tricks in Linux and on the Shell. I will expand it in the future :)
Use Git to manage your Config Files
If you have config files, that you change from time to time, make a (local-only or also remote) Git Repository out of it! This brings a couple of handy features and benefits such like:
- Change History: As you can use Git to view the changes of each commit you can easily do rollbacks and you know what your colleagues did before they went on vacation.
- Backup Solution: If you also push your changes to a Git server you can also have a simple backup solution for them.
- Git as a Rescue System: Breaking changes and accidentally deleted or overwritten files are no longer a problem for you, just revert the happy little accident.
- Quick Checkouts: As you can do checkouts and diffs between every commit you can also compare more complicated situations without having to struggle with juggling between multiple copies.
Fast Copy
You may have noticed that copying a very large or a lot of files can be quite slow with cp. As a workaround you can compress them with tar, before you pipe them to another tar in a different directory:
tar cf - . | (cd /your/destination; tar xvf -)
You can add pv to the command to get a more verbose output:
tar cf - . | pv | (cd /dst; tar xf -)
Try and Catch
Also known as for example try / except
in Python.
You will probably be familiar with the logical operators on the Shell to control the flow of a set of commands by each previous return value (such as AND &&
and OR
||):
command1 && \
run_this_when_command1_succeeded || \
run_this_when_command1_failed
This type of code can become hard to follow when getting more complex with multiple ANDs and ORs. To avoid this problem, you can also use a workaround using braces { ... }
to group commands:
{ # try
command1
} || { # catch
run_this_when_command1_failed
}
A longer example:
{ # try
command1 &&
run_this_when_command1_succeeded &&
echo This worked! &&
exit 0
} || { # first catch
{ # another try inside first catch
run_this_when_command1_failed &&
echo First command failed but second succeeded! &&
exit 1
} || { # second catch
run_this_when_first_catch_failed &&
exit 2
}
}
Modern Data Stream Redirection and Piping
Redirecting and Piping the output of data streams like stderr to stdout is one of the most used features in Linux.
Redirection
With Bash Version 4 a new abbreviation for 2>&1
was introduced: >&
Example:
root@local:~$ rm missing-file
rm: cannot remove 'missing-file': No such file or directory
root@local:~$ rm missing-file >& command_output.txt
root@local:~$ cat command_output.txt
rm: cannot remove 'missing-file': No such file or directory
root@local:~$
Piping
Instead of command 2>&1 | tee -a logfile.log
you can also use command |& tee -a logfile.log
to pipe both data streams.
Bash Variable with default Value
This is something I saw on Stackexchange and found very useful as it helps to write clean code.
You can assign a default value to a variable if the value of another, passed variable is either empty or undefinied.
NOTE: This “other variable” can be the same or another variable.
excerpt
${parameter:-word}
If parameter is unset or null, the expansion of word is substituted.
Otherwise, the value of parameter is substituted.
NOTE: This form also works, ${parameter-word}. If you’d like to see a full list of all forms of parameter expansion available within Bash then I highly suggest you take a look at this topic in the Bash Hacker’s wiki titled: “Parameter expansion”.
Examples
variable doesn’t exist
$ echo "$VAR1"
$ VAR1="${VAR1:-default value}"
$ echo "$VAR1"
default value
variable exists
$ VAR1="has value"
$ echo "$VAR1"
has value
$ VAR1="${VAR1:-default value}"
$ echo "$VAR1"
has value
More Examples
$ echo "${VAR1-0}"
has another value
$ echo "${VAR2-0}"
has another value
$ echo "${VAR3-0}"
0
$ VARX="${VAR3-0}"
$ echo "$VARX"
0
In the above $VAR1
& $VAR2
were already defined with the string “has another value” but $VAR3
was undefined, so the default value was used instead, 0
.
Evaluating a variable with another
The same thing can be done by evaluating other variables, or running commands within the default value portion of the notation.
$ VAR2="has another value"
$ echo "$VAR2"
has another value
$ echo "$VAR1"
$
$ VAR1="${VAR1:-$VAR2}"
$ echo "$VAR1"
has another value
Checking and assigning using := notation
Lastly I’ll mention the handy operator, :=
. This will do a check and assign a value if the variable under test is empty or undefined.
Example
Notice that $VAR1
is now set. The operator :=
did the test and the assignment in a single operation.
$ unset VAR1
$ echo "$VAR1"
$ echo "${VAR1:=default}"
default
$ echo "$VAR1"
default
However if the value is set prior, then it’s left alone.
$ VAR1="some value"
$ echo "${VAR1:=default}"
some value
$ echo "$VAR1"
some value
Reference Table
Set and Not Null | Set But Null | Unset | |
---|---|---|---|
${parameter:-word} | substitute parameter | substitute word | substitute word |
${parameter-word} | substitute parameter | substitute null | substitute word |
${parameter:=word} | substitute parameter | assign word | assign word |
${parameter=word} | substitute parameter | substitute null | assign word |
${parameter:?word} | substitute parameter | error, exit | error, exit |
${parameter?word} | substitute parameter | substitute null | error, exit |
${parameter:+word} | substitute word | substitute null | substitute null |
${parameter+word} | substitute word | substitute word | substitute null |