Table of Contents

Bash

Startup

Startup

Des raccourcis utiles

La dernière commande

$ vim todo.txt
$ mv [alt + .]todo.txt ~/tmp
C'est utile si vous faites une erreur du genre :
$ vim cd ~/downloads
$ !*
ce qui donnera
$ cd ~/downloads
Un exemple:
$ ping -c 3 linuxfr.org
$ !:- framasoft.org
Ce qui donnera
$ ping -c 3 framasoft.org

Builtin

See all bash builtins. Type the following command:

$ help
$ help | less

Substitution

Summary: String Manipulation and Expanding Variables

For your ready references here are all your handy bash parameter substitution operators.

${parameter:-defaultValue}	Get default shell variables value
${parameter:=defaultValue}	Set default shell variables value
${parameter:?"Error Message"}	Display an error message if parameter is not set
${#var}	Find the length of the string
${var%pattern}	Remove from shortest rear (end) pattern
${var%%pattern}	Remove from longest rear (end) pattern
${var:num1:num2}	Substring
${var#pattern}	Remove from shortest front pattern
${var##pattern}	Remove from longest front pattern
${var/pattern/string}	Find and replace (only replace first occurrence)
${var//pattern/string}	Find and replace all occurrences

Setting Up Default Shell Variables Value

The syntax is as follows:

${parameter:-defaultValue}
var=${parameter:-defaultValue}

If parameter not set, use defaultValue.

Setting Default Values

The syntax is as follows:

${var:=value}
var=${USER:=value}

The assignment ( := ) operator is used to assign a value to the variable if it doesn't already have one.

Display an Error Message If $VAR Not Passed

If the variable is not defined or not passed, you can stop executing the Bash script with the following syntax:

${varName?Error varName is not defined}
${varName:?Error varName is not defined or is empty}
${1:?"mkjail: Missing operand"}
MESSAGE="Usage: mkjail.sh domainname IPv4"             ### define error message
_domain=${2?"Error: ${MESSAGE}"}  ### you can use $MESSAGE too

This is used for giving an error message for unset parameters.

Find Variable Length

You can easily find string length using the following syntax:

${#variableName}
echo ${#variableName}
len=${#var}

Remove Pattern (Front of $VAR)

The syntax is as follows:

${var#Pattern}
${var##Pattern}

The first syntax removes shortest part of pattern and the second syntax removes the longest part of the pattern.

Remove Pattern (Back of $VAR)

The syntax is as follows:

${var%pattern}
${var%%pattern}

Exactly the same as above, except that it applies to the back of $var.

Find And Replace

The syntax is as follows:

${varName/Pattern/Replacement}
${varName/word1/word2}
${os/Unix/Linux}

To replace all matches of pattern, enter :

out="${x//unix/linux}"

Substring Starting Character

The syntax is as follows:

${parameter:offset}
${parameter:offset:length}
${variable:position}
var=${string:position}

Expands to up to length characters of parameter starting at the character specified by offset.

Autocomplete SSH host

complete -W "$(echo `cat ~/.ssh/known_hosts | cut -f 1 -d ' ' | sed -e s/,.*//g | uniq | grep -v "\["`;)" ssh scp sftp

PV

Copier un fichier avec progression pv Pour copier un fichier, on va utiliser uniquement la commande pv :

pv fic-source > fic-dest

Ce qui donne par exemple :

pv Fedora-Cinnamon-Live-x86_64-24_Beta-1.6.iso > copie.iso
1.28GiO 0:00:02 [ 529MiB/s] [==========================>] 100%

Créer une clé USB bootable avec dd et pv Pour créer une clé USB (/dev/sdc) bootable d'une ISO Linux, la commande est :

dd if=fichier-image-linux.iso of=/dev/sdc

Dorénavant, on peut utiliser avec pv pour avoir une progression de l'avancement de la copie :

pv fichier-image-linux.iso | dd of=/dev/sdc

Ce qui donne en fin de copie ceci : (Imaginer le curseur ===⇒ avancer au cours de la copie)

pv fichier-image-linux.iso | dd of=/dev/sdc
1,41GiO 0:00:54 [26,5MiB/s] [=======================================================>] 100%
2965504+0 enregistrements lus
2965504+0 enregistrements écrits
1518338048 octets (1,5 GB) copiés, 54,5804 s, 27,8 MB/s

Créer une archive compressée .tar.gz Coupler tar et pv est possible, utiliser comme ceci :

tar -czf - dossier | pv > archive.tar.gz

Décompresser une archive .tar.gz Pour décompresser, même principe que la compression, mais à l'envers :

pv sox.tar.gz |tar xzf -
/code>

===== Rm except =====
  * Delete all file except file1
<code>rm  !(file1)
rm  !(file1|file2)
rm  !(*.zip)
rm  !(*.zip|*.iso)
rm /Users/vivek/!(*.zip|*.iso|*.mp3)
rm [options]  !(*.zip|*.iso)
rm -v  !(*.zip|*.iso)
rm -f  !(*.zip|*.iso)
rm -v -i  !(*.php)

Return codes

Exit Code Description
0Success
1Operation not permitted
2No such file or directory
3No such process
4Interrupted system call
5Input/output error
6No such device or address
7Argument list too long
8Exec format error
9Bad file descriptor
10No child processes
11Resource temporarily unavailable
12Cannot allocate memory
13Permission denied
14Bad address
15Block device required
16Device or resource busy
17File exists
18Invalid cross-device link
19No such device
20Not a directory
21Is a directory
22Invalid argument
23Too many open files in system
24Too many open files
25Inappropriate ioctl for device
26Text file busy
27File too large
28No space left on device
29Illegal seek
30Read-only file system
31Too many links
32Broken pipe
33Numerical argument out of domain
34Numerical result out of range
35Resource deadlock avoided
36File name too long
37No locks available
38Function not implemented
39Directory not empty
40Too many levels of symbolic links
42No message of desired type
43Identifier removed
44Channel number out of range
45Level 2 not synchronized
46Level 3 halted
47Level 3 reset
48Link number out of range
49Protocol driver not attached
50No CSI structure available
51Level 2 halted
52Invalid exchange
53Invalid request descriptor
54Exchange full
55No anode
56Invalid request code
57Invalid slot
59Bad font file format
60Device not a stream
61No data available
62Timer expired
63Out of streams resources
64Machine is not on the network
65Package not installed
66Object is remote
67Link has been severed
68Advertise error
69Srmount error
70Communication error on send
71Protocol error
72Multihop attempted
73RFS specific error
74Bad message
75Value too large for defined data type
76Name not unique on network
77File descriptor in bad state
78Remote address changed
79Can not access a needed shared library
80Accessing a corrupted shared library
81.lib section in a.out corrupted
82Attempting to link in too many shared libraries
83Cannot exec a shared library directly
84Invalid or incomplete multibyte or wide character
85Interrupted system call should be restarted
86Streams pipe error
87Too many users
88Socket operation on non-socket
89Destination address required
90Message too long
91Protocol wrong type for socket
92Protocol not available
93Protocol not supported
94Socket type not supported
95Operation not supported
96Protocol family not supported
97Address family not supported by protocol
98Address already in use
99Cannot assign requested address
100Network is down
101Network is unreachable
102Network dropped connection on reset
103Software caused connection abort
104Connection reset by peer
105No buffer space available
106Transport endpoint is already connected
107Transport endpoint is not connected
108Cannot send after transport endpoint shutdown
109Too many references
110Connection timed out
111Connection refused
112Host is down
113No route to host
114Operation already in progress
115Operation now in progress
116Stale file handle
117Structure needs cleaning
118Not a XENIX named type file
119No XENIX semaphores available
120Is a named type file
121Remote I/O error
122Disk quota exceeded
123No medium found
125Operation canceled
126Required key not available
127Key has expired
128Key has been revoked
129Key was rejected by service
130Owner died
131State not recoverable
132Operation not possible due to RF-kill
133Memory page has hardware error

Tests (BATS)

Lorsque que l'on écrit le script suivant foo.sh:

#!/usr/bin/env bash

foo() {
    echo "Hello World!"
}

foo
exit 1

on peut écrire un fichier de test test.bats:

#!/usr/bin/env bats

@test "test sur l'output dans stdout" {
    run bash foo.sh
        [ "${lines[0]}" = "Hello World!" ]
}

@test "test sur l'exit code" {
    run bash foo.sh
        [ "$status" -eq 0 ]
}

et lancer la commande:

bats test.bats

Cela fournit le résultat suivant:

✓ test sur l'output dans stdout
✗ test sur l'exit code
    (in test file test.bats, line 10)
        `[ "$status" -eq 0 ]' failed

2 tests, 1 failure

Version comparison

#!/bin/bash
vercomp () {
    if [[ $1 == $2 ]]
    then
        return 0
    fi
    local IFS=.
    local i ver1=($1) ver2=($2)
    # fill empty fields in ver1 with zeros
    for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
    do
        ver1[i]=0
    done
    for ((i=0; i<${#ver1[@]}; i++))
    do
        if [[ -z ${ver2[i]} ]]
        then
            # fill empty fields in ver2 with zeros
            ver2[i]=0
        fi
        if ((10#${ver1[i]} > 10#${ver2[i]}))
        then
            return 1
        fi
        if ((10#${ver1[i]} < 10#${ver2[i]}))
        then
            return 2
        fi
    done
    return 0
}