This post list a few tips that I discovered when I started working back in 2013. I have improved my knowledge a great deal over the last years but the informations there can still be useful.
Bash (any)
Use a default value if the variable is unset or null (see more on parameter expansion):
echo "${TEST:-default}"
Transfer the parameters to a command:
test.sh:
my_function "$@"
test.sh "this has spaces" 25
=> my_function will correctly receive 2 parameters: "this has spaces" and 25. If you use $@ without quotes or $*, the quoting would be lost and my_function would receive 4 parameters: "this", "has", "spaces" and "25"
Repeat last command :
!!
Substitute A for B in the last command and execute it:
^A^B^
Use the last item of the last command in the current one:
ls /tmp /tmp2
cd !$
pwd -> /tmp
For the first item of the last command (^
and $
match regexes):
ls /tmp /tmp2
cd !^
pwd -> /tmp2
Print every command before execution. Very useful when debugging bash scripts:
set -x
Exit the script at the first error (Note: beware grep)
set -e
Generally speaking, to increase the reliability of your scripts and prevent silent errors, this construct should be preferred:
set -eu
set -o pipefail
-e
: exit on error (warning: will not raise an error if the failing process is part of a pipe)-u
: using undefined variables trigger an error-o pipefail
: if a process fail in a pipe, trigger an error
Zsh
List any compressed file in any sub-directory **/*
ending with either bz2 or gz with a size greater than 10MB (Lm+10)
ls -lh **/*.(bz2|gz)(Lm+10)
Print only the basename (t), the dirname (h) or the file name and directory without the extension (r) of the variable FILE
ls "${FILE:t}"
ls "${FILE:h}"
ls "${FILE:r}"
Arrays
Create a new Array:
IDs=(ber_sim boi_mar bom_cel bou_pat che_elo cha_chr)
Print length of Array:
echo "${#IDs}"
Loop
Print numbers from 1 to 5, instead of using seq
:
for i in {1..5}; do echo $i; done
find
Print the directory (%h), the file name (%f) and the size in kB (%k) of any tar.bz2 archive bigger than 20MB in subdirectories:
find -iname "*.tar.bz2" -size +20M -printf '%ht%ft%kkn'
Copy any .sh file in subdirectories to the current directory:
find -name "*.sh" -exec cp '{}' . ;
awk
Select the second column of each line from command qjob, and for each selected part of line, execute qdel
qjob -l | awk '{print $2}' | while read i; do qdel $i
print the 4th value divided by 172 followed by a semicolon and the 8th value of each line of the file File.log . Two delimiters are used at the same time: :
and ,
awk -F':|,' '{print $4/172 ";" $8}' File.log
More Infos
How to make portable tests in bash, or what are the differences between [ and [[