====== Bash ======
===== Startup =====
{{:bash-startup-files.png|Startup}}
===== Des raccourcis utiles ====
* Ctrl + a : Pour aller au début de la ligne
* Ctrl + e : Pour aller à la fin de la ligne
* Ctrl + b : Pour se déplacer d'un caractère vers l'arrière (flèche gauche)
* Ctrl + f : Pour se déplacer d'un caractère vers l'avant (flèche droite)
* Alt + b : Pour se déplacer d'un mot vers l'arrière
* Alt + f : Pour se déplacer d'un mot vers l'avant
* Ctrl + xx : Pour passer de la position du curseur au début de la ligne et revenir à la position où se trouvait le curseur
* TAB : Pour compléter automatiquement les noms de fichiers/dossiers/commandes
* Ctrl + d : Pour effacer le caractère sur lequel se trouve le curseur
* Ctrl + h : Pour effacer le caractère précédant le curseur (la fonction classique du retour arrière)
* Alt + d : Pour effacer le mot suivant le curseur
* Alt + retour arrière : Pour effacer le mot précédant le curseur
* Ctrl + l : Pour nettoyer l'écran (l'équivalent de la commande clear)
* Alt + t : Pour échanger la place du mot où se trouve le curseur avec celui le précédant
* Ctrl + t : Pour échanger la place des deux caractères précédant le curseur
* Ctrl + w : Pour couper le mot précédant le curseur
* Ctrl + k : Pour couper la partie de la ligne suivant le curseur
* Ctrl + u : Pour couper la partie de la ligne précédant le curseur
* Ctrl + y : Pour coller la dernière chose coupée
* Ctrl + _ : Pour annuler la dernière modification (undo)
* Ctrl + j : Pour créer une nouvelle ligne
* Ctrl + c : Pour arrêter la commande en cours et créer aussi une nouvelle ligne
* Ctrl + r : Pour rechercher une commande précédente dans l'historique
* Ctrl + g : Pour quitter la recherche dans l'historique
* Ctrl + p : Commande précédente (flèche haut)
* Ctrl + n : Commande suivante (flèche bas)
* Ctrl + x + e : Pour lancer un traitement de texte (nano par ex.) pour écrire une longue commande.
===== La dernière commande =====
* !! : Pour répéter la dernière commande
* alt + . : Pour ajouter le dernier argument de la dernière commande
$ vim todo.txt
$ mv [alt + .]todo.txt ~/tmp
* !$ : Egalement utile pour ajouter le dernier argument de la dernière commande
* !* : Pour reproduire tous les arguments de la dernière commande
C'est utile si vous faites une erreur du genre :
$ vim cd ~/downloads
$ !*
ce qui donnera
$ cd ~/downloads
* !foo : Pour réutiliser la dernière commande en commençant par foo (on peut aussi faire foo !!)
* !:- : Pour réutiliser la dernière commande sans le dernier argument
Un exemple:
$ ping -c 3 linuxfr.org
$ !:- framasoft.org
Ce qui donnera
$ ping -c 3 framasoft.org
* A ces commandes, vous pouvez ajouter à la fin :p (par ex. !*:p) pour afficher la commande sans qu'elle se lance.
===== 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
rm !(file1)
* Delete all file except file1 and file2
rm !(file1|file2)
* Delete all file except all zip files
rm !(*.zip)
* Delete all file except all zip and iso files
rm !(*.zip|*.iso)
* You set full path too
rm /Users/vivek/!(*.zip|*.iso|*.mp3)
* Pass options
rm [options] !(*.zip|*.iso)
rm -v !(*.zip|*.iso)
rm -f !(*.zip|*.iso)
rm -v -i !(*.php)
===== Return codes =====
^Exit Code ^ Description^
|0|Success|
|1|Operation not permitted|
|2|No such file or directory|
|3|No such process|
|4|Interrupted system call|
|5|Input/output error|
|6|No such device or address|
|7|Argument list too long|
|8|Exec format error|
|9|Bad file descriptor|
|10|No child processes|
|11|Resource temporarily unavailable|
|12|Cannot allocate memory|
|13|Permission denied|
|14|Bad address|
|15|Block device required|
|16|Device or resource busy|
|17|File exists|
|18|Invalid cross-device link|
|19|No such device|
|20|Not a directory|
|21|Is a directory|
|22|Invalid argument|
|23|Too many open files in system|
|24|Too many open files|
|25|Inappropriate ioctl for device|
|26|Text file busy|
|27|File too large|
|28|No space left on device|
|29|Illegal seek|
|30|Read-only file system|
|31|Too many links|
|32|Broken pipe|
|33|Numerical argument out of domain|
|34|Numerical result out of range|
|35|Resource deadlock avoided|
|36|File name too long|
|37|No locks available|
|38|Function not implemented|
|39|Directory not empty|
|40|Too many levels of symbolic links|
|42|No message of desired type|
|43|Identifier removed|
|44|Channel number out of range|
|45|Level 2 not synchronized|
|46|Level 3 halted|
|47|Level 3 reset|
|48|Link number out of range|
|49|Protocol driver not attached|
|50|No CSI structure available|
|51|Level 2 halted|
|52|Invalid exchange|
|53|Invalid request descriptor|
|54|Exchange full|
|55|No anode|
|56|Invalid request code|
|57|Invalid slot|
|59|Bad font file format|
|60|Device not a stream|
|61|No data available|
|62|Timer expired|
|63|Out of streams resources|
|64|Machine is not on the network|
|65|Package not installed|
|66|Object is remote|
|67|Link has been severed|
|68|Advertise error|
|69|Srmount error|
|70|Communication error on send|
|71|Protocol error|
|72|Multihop attempted|
|73|RFS specific error|
|74|Bad message|
|75|Value too large for defined data type|
|76|Name not unique on network|
|77|File descriptor in bad state|
|78|Remote address changed|
|79|Can not access a needed shared library|
|80|Accessing a corrupted shared library|
|81|.lib section in a.out corrupted|
|82|Attempting to link in too many shared libraries|
|83|Cannot exec a shared library directly|
|84|Invalid or incomplete multibyte or wide character|
|85|Interrupted system call should be restarted|
|86|Streams pipe error|
|87|Too many users|
|88|Socket operation on non-socket|
|89|Destination address required|
|90|Message too long|
|91|Protocol wrong type for socket|
|92|Protocol not available|
|93|Protocol not supported|
|94|Socket type not supported|
|95|Operation not supported|
|96|Protocol family not supported|
|97|Address family not supported by protocol|
|98|Address already in use|
|99|Cannot assign requested address|
|100|Network is down|
|101|Network is unreachable|
|102|Network dropped connection on reset|
|103|Software caused connection abort|
|104|Connection reset by peer|
|105|No buffer space available|
|106|Transport endpoint is already connected|
|107|Transport endpoint is not connected|
|108|Cannot send after transport endpoint shutdown|
|109|Too many references|
|110|Connection timed out|
|111|Connection refused|
|112|Host is down|
|113|No route to host|
|114|Operation already in progress|
|115|Operation now in progress|
|116|Stale file handle|
|117|Structure needs cleaning|
|118|Not a XENIX named type file|
|119|No XENIX semaphores available|
|120|Is a named type file|
|121|Remote I/O error|
|122|Disk quota exceeded|
|123|No medium found|
|125|Operation canceled|
|126|Required key not available|
|127|Key has expired|
|128|Key has been revoked|
|129|Key was rejected by service|
|130|Owner died|
|131|State not recoverable|
|132|Operation not possible due to RF-kill|
|133|Memory 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
}