Bash

Mitigate typos and errors in your scripts

# Tell bash that it should exit your script if any statement 
# returns a non true return value:
set -e
 
# This will exit your script if you try to use an uninitialized 
# variable:
set -u

Some useful bash shell constructs or one liners:

This will be suitable for a huge amount of iterations:

for ((a=0; a <= 5 ; a++)) do mkdir weekly.$a; done

or a little bit simpler

for i in 0 1 2 3; do mkdir weekly.$i; done

or even more short and simple

mkdir weekly.{1,2,3,4}

Every variation will create 4 directories: weekly.0 weekly.1 … weekly.4

Something special:

for i in *; do cd $i; [ -d somedir ] && rm -r somedir; cd ..; done

List the current directory (assumed there are only directories, no files). Go into every subdirectory ($i). Look if there is “somedir”. If it exists rm -r somedir. Move back and go into the next directory ($i)…

Adding new line character in a for loop:

for i in *.conf;
do
    (cat "${i}"; echo) >> big.conf
done;

If you are dealing with files which are ending without a trailing new line, this construct will fix the issue. Without the parenthesis you'll only get a newline at the end of the destination file.

Read a File Line by Line:
Assumption: you ran find to create a file with filenames. Now you want to just print the files for a quick check:

# create a file with filenames
find /var/www -name '.htaccess' -exec grep -l Basic {} \; > file
 
# iterate and print the files:
while read line; do cat "$line"; done < file

Dotfiles and globbing
Have you ever tried to just du, how much space these damn dot-directories consume? You'll have quite some fun trying to defeat bash's dotfile globbing.
Here is the solution:

du -hsm .[^.]*

Bash Dotfiles or Startup Files

In which order bash read its dotfiles aka startup files (.bash_profile, .bashrc, .bash_login, etc.) when invoked as a login shell or nonlogin shell:

Bash interactive login shell
To start a login shell, invoke bash like so:

  • /bin/bash -l
  • /bin/bash –login

Startup files are read in the following order:

  1. /etc/profile
  2. ~/.bash_profile
  3. ~/.bash_login
  4. ~/.profile

When a login shell exits, bash reads an executes from

  • ~/.bash_logout

Bash interactive nonlogin shell
Startup files are read in the following order:

  1. /etc/bash.bashrc
  2. ~/.bashrc

An example dotfile:

# be colorful
export LS_OPTIONS='--color=auto'
eval `dircolors`
 
# command shortcuts
alias la='ls -la'
 
# user <> root -> sudo
SUDO_PREFIX=''
if [ $UID -ne 0 ]; then
    SUDO_PREFIX='sudo '
fi
 
alias tm="${SUDO_PREFIX}tail -n35 /var/log/messages"
alias tw="${SUDO_PREFIX}tail -n35 /var/log/syslog"
 
# navigation optimized
alias ..='cd ..'
alias ...='cd ../..'
alias cds='cd /usr/src'
alias cdl='cd /usr/local'
alias cdi='cd /etc/init.d'
alias cde='cd /etc'
 
# bash history adjusted
export HISTCONTROL=ignoreboth
export HISTIGNORE='ls:la:ll:history:df:sar:tm:tw'
export HISTFILESIZE=100000
export HISTSIZE=100000
shopt -s histappend
 
# be git-friendly
if [ -f /etc/bash_completion.d/git ]; then
    . /etc/bash_completion.d/git
    PS1='\u@\h:\w$(__git_ps1 "[%s]")\$ '
fi

reformat markup for dokuwiki

Transform data:
The data is given in the following form:

1.3. 19.00 YouGo-Team
2.3. 19.00 Weltgebetstag in der Christuskirche, Ohmbach
6.3. 20.00 Probe Liturgischer Singkreis

and should be formatted for dokuwiki tables:

^1.3.|19.00 Uhr| YouGo-Team|
^2.3.|19.00 Uhr| Weltgebetstag in der Christuskirche, Ohmbach|
^6.3.|20.00 Uhr| Probe Liturgischer Singkreis|
#!/bin/bash
set -u
set -e
 
while read line 
do
	# extract date
        DATUM=$(echo $line | cut -d ' ' -f1)
        # extract time
	ZEIT=$(echo $line | cut -d ' ' -f2)
        # remove date from from $line
	line=${line#$DATUM}
        # remove time from $line
	line=${line# $ZEIT}
        # some special formatting to do rowspan
	if [ $DATUM == ":::" ]; then
		DATUM=" ::: "
	fi
        # center '-' in table col
	if [ $ZEIT == "-" ]; then
		ZEIT='  -  '
	else
                # append the Word "Uhr" to time
		ZEIT="$ZEIT Uhr"
	fi
        # reassemble the output line:
	OUTPUT="^${DATUM}|${ZEIT}|$line|"
	echo ${OUTPUT}
done < "termine-neu"

And another one:

Data given:

1. Juni Matthias heißt der „neue Mann“.(Apostelgeschichte 1,15-26)
8. Juni Alle sind an einem Ort. (Apostelgeschichte 2)
15. Juni Alle KiGo-Kinder sind zum Tauferinnerungsgottesdienst in Herschweiler-Pettersheim eingeladen.
22. Juni „Silber und Gold habe ich nicht“, sagt Petrus. (Apostelgeschichte 3,1-11)
29. Juni Heute feiern wir Sommerfest in Herschweiler-Pettersheim.

Shall be tranformed to:

|{{:gottesdienste:kirche_mit_kindern.jpg?nolink&90|KiGo}}^1. Juni| Matthias heißt der „neue Mann“.(Apostelgeschichte 1,15-26)|
|:::^8. Juni| Alle sind an einem Ort. (Apostelgeschichte 2)|
|:::^15. Juni| Alle KiGo-Kinder sind zum Tauferinnerungsgottesdienst in Herschweiler-Pettersheim eingeladen.|
|:::^22. Juni| „Silber und Gold habe ich nicht“, sagt Petrus. (Apostelgeschichte 3,1-11)|

The script which will do the work:

#!/bin/bash
set -u
set -e
 
PREFIX="|{{:gottesdienste:kirche_mit_kindern.jpg?nolink&90|KiGo}}^"
 
while read line
do
        # extract date
        DATUM=$(echo $line | cut -d ' ' -f1,2)
        # remove date from from $line
        line=${line#$DATUM}
        # reassemble the output line:
        OUTPUT="${PREFIX}${DATUM}|$line|"
        echo ${OUTPUT}
        PREFIX="|:::^"
done < "kigo.txt"
shell/bash.txt · Last modified: 2016-02 by tb
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0 ipv6 ready