Outils pour utilisateurs

Outils du site


Panneau latéral

linux:bash (lu 50615 fois)

Bash

Un site qu’il est bien pratique http://www.shellunix.com/commandes.html

Un autre bien détaillé sur le bash http://aral.iut-rodez.fr/fr/sanchis/enseignement/bash/index.html

La bible en anglais du GNU Bash ⇒ http://wiki.bash-hackers.org/start

Le guide du débutant, ici l’introduction au if ⇒ http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html

Se replacer dans le répertoire du script automatiquement

#!/bin/bash
cd `dirname $0`
  • $1 est le 1er argument passé au script, $2 le 2ème etc.. A partir de 10, on note ${10}
  • $0 Contient le nom du script tel qu’il a été invoqué
  • $* L’ensembles des paramètres sous la forme d’un seul argument
  • $@ L’ensemble des arguments, un argument par paramètre
  • $# Le nombre de paramètres passés au script
  • $? Le code retour de la dernière commande
  • $$ Le PID su shell qui exécute le script
  • $! Le PID du dernier processus lancé en arrière-plan
  • $RANDOM Une valeur numeric au hasard
  • $SECONDS Valeur numéric s’incrémentant toutes les secondes, utile pour chronométrer un script

Bang (!) commands

Re-run all or part of a previous command.
Event Designators. An event designator is a reference to a command line entry in the history list. Unless the reference is absolute, events are relative to the current position in the history list.

  • !! Run the last command again
  • !n Refer to command line n.
  • !-n Refer to the current command minus n.
  • !foo Run the most recent command that starts with ‘foo’ (e.g. !ls)
  • !foo:p Print out the command that !foo would run also add it to the command history
  • !$ Run the last word of the previous command (same as Alt + .)
  • !$:p Print out the word that !$ would substitute
  • ! Run the previous command except for the last word * !:p Print out the previous command except for the last word
  • ^foo^bar Run the previous command replacing foo with bar
  • !# The entire command line typed so far.

Variable

toto=lol
echo $toto
echo ${toto}
cpt=1
echo $((cpt++))
echo $((cpt+15))

Tableau associatif ( http://www.artificialworlds.net/blog/2012/10/17/bash-associative-array-examples/ )

$ declare -A MYMAP     # Create an associative array
$ MYMAP[foo]=bar       # Put a value into an associative array
$ echo ${MYMAP[foo]}   # Get a value out of an associative array
bar
$ echo MYMAP[foo]      # WRONG
MYMAP[foo]
$ echo $MYMAP[foo]     # WRONG
[foo]

$ K=baz
$ MYMAP[$K]=quux       # Use a variable as key to put a value into an associative array
$ echo ${MYMAP[$K]}    # Use a variable as key to extract a value from an associative array
quux
$ echo ${MYMAP[baz]}   # Obviously the value is accessible via the literal key
quux

$ declare -A MYMAP=( [foo a]=bar [baz b]=quux )
$ echo "${!MYMAP[@]}"  # Print all keys - quoted, but quotes removed by echo
foo a baz b

$ # Looping through keys and values in an associative array
$ for K in "${!MYMAP[@]}"; do echo $K --- ${MYMAP[$K]}; done
foo a --- bar
baz b --- quux

$ # Loop through all values in an associative array
$ for V in "${MYMAP[@]}"; do echo $V; done
bar
quux

$ echo ${#MYMAP[@]}  # Number of keys in an associative array
2

Faire une liste simple

list=(
  aaa
  bbb
  ccc
  ddd
)

$ echo $list
aaa

$ echo ${list[@]}
aaa bbb ccc ddd

$ echo ${list[1]}
bbb

$ for i in ${list[@]}; do echo $i; done
aaa
bbb
ccc
ddd

Manipuler du texte

Taille d'un texte

stringZ=abcABC123ABCabc
 
echo ${#stringZ}                 # 15
echo `expr length $stringZ`      # 15
echo `expr "$stringZ" : '.*'`    # 15

Position d'un texte dans un texte

stringZ=abcABC123ABCabc
#       123456 ...
echo `expr index "$stringZ" C12`             # 6
                                             # C position.
 
echo `expr index "$stringZ" 1c`              # 3
# 'c' (in #3 position) matches before '1'.

Extraite une partie du texte

stringZ=abcABC123ABCabc
#       0123456789.....
#       0-based indexing.
 
echo ${stringZ:0}                            # abcABC123ABCabc
echo ${stringZ:1}                            # bcABC123ABCabc
echo ${stringZ:7}                            # 23ABCabc
 
echo ${stringZ:7:3}                          # 23A
                                             # Three characters of substring.
 
 
 
# Is it possible to index from the right end of the string?
 
echo ${stringZ:-4}                           # abcABC123ABCabc
# Defaults to full string, as in ${parameter:-default}.
# However . . .
 
echo ${stringZ:(-4)}                         # Cabc 
echo ${stringZ: -4}                          # Cabc
# Now, it works.
# Parentheses or added space "escape" the position parameter.
 
# Thank you, Dan Jacobson, for pointing this out.

Remplacer du texte dans un texte

stringZ=abcABC123ABCabc
 
echo ${stringZ/abc/xyz}       # xyzABC123ABCabc
                              # Replaces first match of 'abc' with 'xyz'.
 
echo ${stringZ//abc/xyz}      # xyzABC123ABCxyz
                              # Replaces all matches of 'abc' with # 'xyz'.
 
echo  ---------------
echo "$stringZ"               # abcABC123ABCabc
echo  ---------------
                              # The string itself is not altered!
 
# Can the match and replacement strings be parameterized?
match=abc
repl=000
echo ${stringZ/$match/$repl}  # 000ABC123ABCabc
#              ^      ^         ^^^
echo ${stringZ//$match/$repl} # 000ABC123ABC000
# Yes!          ^      ^        ^^^         ^^^
 
echo
 
# What happens if no $replacement string is supplied?
echo ${stringZ/abc}           # ABC123ABCabc
echo ${stringZ//abc}          # ABC123ABC
# A simple deletion takes place.
 
echo ${stringZ/#abc/XYZ}          # XYZABC123ABCabc
                                  # Replaces front-end match of 'abc' with 'XYZ'.
 
echo ${stringZ/%abc/XYZ}          # abcABC123ABCXYZ
                                  # Replaces back-end match of 'abc' with 'XYZ'.

Lire un fichier

#!/bin/bash
# Usage: $0 < FILENAME
 
while read line  # Boucle sur chaque ligne du fichier
do
  echo "$line"   # Affiche la ligne en cours
 
  len=${#line}   # taille de la ligne
 
done

ou

#!/bin/bash
while read line  # Boucle sur chaque ligne du fichier
do
  echo "$line"   # Affiche la ligne en cours
done < /home/user/mon_fichier

Traiter un fichier csv

#!/bin/bash
while IFS=';' read champ1 champ2 champ3  # déclarez autant de champ séparé par un ;
do
  echo "$champ1 $champ2 $champ3"   # Affiche les champs
done < /home/user/mon_fichier.csv

Test d'exécution d'une commande

La 1ère façon la plus simple est d’utiliser && et ||

command && echo "tout est ok" || echo "la commande a échoué"

Dans des cas plus complexe, vous pouvez créer une fonction dans un fichier mesfonctions que vous pouvez inclure facilement dans d’autres scripts avec la commande

. /cheminde/mesfonctions

ou

source /chemeinde/mesfonctions
run() {
        # Vous pouvez lancer ici une pre-command
        # on exécute la commande passée en paramètre
        $@ 
        if [ $? -ne 0 ]
        then
                #si le code retour est différent de zéro, cela signifie que la commande a échoué
                echo "Big problème !!!"
                return 1
        else
                #sinon tout est ok
                echo "Good !"
                return 0
        fi
}

Exemple de condition

Voila un petit bout de bash pour tester l’existence d’un repertoire ou d’un fichier

#!/bin/bash
dir="/home/hio/test"
if [ -d "$dir" ]; then
    echo "$dir existe !"
fi

et en rajoutant un else ^^

#!/bin/bash
dir="/home/hio/test"
if [ -d "$dir" ]; then
    echo "$dir existe !"
else
    echo "$dir n'existe pas!"
fi

et en inversant le test on rajoute juste un « ! » devant le « -d »

#!/bin/bash
dir="/home/hio/test"
if [ ! -d "$dir" ]; then
    echo "$dir n'existe pas!"
else
    echo "$dir existe !"
fi

Voila, c’est pas tres compliqué ^^ et pour tester l’existence d’un fichier, on remplace juste le « -d » par un « -f »

On peut aussi écrire

if test -f $1
then
	file $1
else
	echo " le fichier n'existe pas "
fi

La commande test permet pas mal de possibilité ( voir man test )

Le fait de mettre -e à la place de -d ou -f est plus pratique car ca test tout sans distinction.

if [ -e index.html ]; then echo OK; fi

Autre facon encore plus courte de faire la même chose

[[e_index.html]] && echo OK

Pour tester le contenu d’une string

VAR="hello"
if [ -n "$VAR" ]; then
    echo "VAR is not empty"
fi
VAR=""
if [ -z "$VAR" ]; then
    echo "VAR is empty"
fi

Tester le contenu d’une chaine avec du regex

Tester une date yyyymmdd de facon très simple

[[ $date =~ ^[0-9]{8}$ ]] && echo "yes"

ou plus complet

[[ $date =~ ^[0-9]{4}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])$ ]] && echo "yes"
#           |^^^^^^^^ ^^^^^^ ^^^^^^  ^^^^^^ ^^^^^^^^^^ ^^^^^^ |
#           |   |     ^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^ |
#           |   |          |                   |              |
#           |   |           \                  |              |
#           | --year--   --month--           --day--          |
#           |          either 01...09      either 01..09     end of line
# start of line            or 10,11,12         or 10..29
#                                              or 30, 31

That is, you can define a regex in Bash matching the format you want. This way you can do:

[[ $date =~ ^regex$ ]] && echo "matched" || echo "did not match"

where commands after && are executed if the test is successful, and commands after || are executed if the test is unsuccessful.

Note this is based on the solution by Aleks-Daniel Jakimenko in User input date format verification in bash.

In other shells you can use grep. If your shell is POSIX compliant, do

(echo "$date" | grep -Eq  ^regex$) && echo "matched" || echo "did not match"

In fish, which is not POSIX-compliant, you can do

echo "$date" | grep -Eq "^regex\$"; and echo "matched"; or echo "did not match"

Boucle

for

for VARIABLE in 1 2 3 4 5 .. N
do
	command1
	command2
	commandN
done

Séquence

for i in {1..5}
do
   echo "Welcome $i times"
done

Affiche les nombres impaires

for i in {1..11..2}
do
   echo "Welcome $i times"
done

plus d’exemple ⇒ http://www.cyberciti.biz/faq/bash-for-loop/

Ecriture sur une ligne de commande

for i in {1..5}; do COMMAND-HERE; done
for X in /dev/sd*; do echo $X; smartctl -a $X | grep overall; done
~# for X in {a..z}; do smartctl -a /dev/sd$X | grep overall; done
SMART overall-health self-assessment test result: PASSED
SMART overall-health self-assessment test result: PASSED
SMART overall-health self-assessment test result: PASSED
SMART overall-health self-assessment test result: PASSED
...

Suppression d'un grand nombre de fichiers

Lorsqu’il y a un grand nombre de fichiers à supprimer, la commande rm ne suffit plus.

Voici 3 facons différentes d’effectuer cette suppression.

On liste les fichiers que l’on veut supprimer avec ls et avec xargs on les envoie en argument un par un à rm

ls * | xargs rm

NOTE : le ls * ne fonctionne pas quand on a trop de fichier…, essayer plutot ceci si vous voulez par exemple effacer tous les fichiers qui contient le mot toto ls | grep toto | xargs rm -f
Si vous souhaitez effacer tous les fichiers du répertoire courant, ceci fonctionnera ls | xargs rm -f A la place de ls on peut aussi utiliser find find . -type f -name * | xargs rm
Ou utiliser find sans xargs find . -name “*” -exec rm {} \; Pour savoir combien de fichiers vont être effacés find . -name “*” | wc -l
Garder les 5 fichiers les plus récents et supprimer le reste ls -c *.txt | tail -n +5 | xargs rm ===== Taille de plusieurs répertoires ===== Permet d’afficher la taille des répertoires du répertoire courant. du -h –max-depth=1 Affiche la taille des répertoires du -hcs * Affiche la taille des répertoires en ignorant les autres disques (sans compter les /mnt, /media..) et trie du plus petit au plus grand. du -xhcs –max-depth=1 | sort -h Compter le nombre de fichier récursivement sans compter les répertoires ls -Rp repertoire | grep -v -e ^$ -e / | wc -l Compter le nombre de répertoire ls -dR repertoire/* | wc -l
Un petit programme nommé ncdu dispo dans les dépots permet d’afficher sous forme graphique la taille des répertoires et de naviguer à l’intérieur ===== Faire un prompt ===== Ce script pose une question à l’utilisateur et la repose tant qu’une réponse valide n’a pas été donnée. <code bash> PS3='> ' # le prompt LISTE=(“[y] yes” “[n] no”) # liste de choix disponibles select CHOIX in “${LISTE[@]}” ; do case $REPLY in yes|y) echo ok break ;; no|n) echo ko break ;; *) echo “invalid option $REPLY”;; esac done </code> Demander de saisir un texte <code bash> echo Hello, who am I talking to? read varname echo It\’s nice to meet you $varname </code> ===== echo ===== Ne pas revenir à la ligne [user@pc]# echo -n blabla blabla[user@pc]#
Autoriser les sequences avec des backslash echo -e blabla\\nbla blabla bla <code>
backslash \a alert (BEL) \b backspace \c produce no further output \e escape \f form feed \n new line \r carriage return \t horizontal tab \v vertical tab \0NNN byte with octal value NNN (1 to 3 digits) \xHH byte with hexadecimal value HH (1 to 2 digits) </code> Dans le cas d’une variable avec retour chariot, echo converti les retours chariots par un espace. Il est possible de faire autrement. Voici un exemple <code bash> [root@pc:~]# free total used free shared buffers cached Mem: 236736 185120 51616 0 80084 16968 -/+ buffers/cache: 88068 148668 Swap: 102396 96 102300 [root@pc:~]# toto=free [root@pc:~]# echo $toto total used free shared buffers cached Mem: 236736 185240 51496 0 80092 16968 -/+ buffers/cache: 88180 148556 Swap: 102396 96 102300 [root@pc:~]# echo “$toto” total used free shared buffers cached Mem: 236736 185240 51496 0 80092 16968 -/+ buffers/cache: 88180 148556 Swap: 102396 96 102300 </code>
===== Ecrire en couleur ===== <code>!/bin/sh VERT=“\\033[1;32m” NORMAL=“\\033[0;39m” ROUGE=“\\033[1;31m” ROSE=“\\033[1;35m” BLEU=“\\033[1;34m” BLANC=“\\033[0;02m” BLANCLAIR=“\\033[1;08m” JAUNE=“\\033[1;33m” CYAN=“\\033[1;36m” echo “” echo -e “$VERT” “ —————— ”“$ROUGE”“Y o u W i l l B e C o l o r e d ”“$VERT”“ ———— ” “$NORMAL” echo “ | Color bash script | ” echo -e “ | written by”“$VERT” “selim,b.” “$CYAN”“(s.bouras@free.fr) ” “$NORMAL” “ | ” echo -e “ | This script is”“$BLEU”“ free Licence”“$NORMAL”“ | ” echo -e “$VERT” “ ——————————————————————– ” “$NORMAL” echo -e “ $BLEU” “ Ok!!..Dear … Your bash is colored .. Have Fun!!..”</code> En php exécuté en mode console, vous pouvez aussi écrire en couleur avec un echo “\033[47m \033[1;34m texte en bleu sur fond gris clair \033[0m \n”; Contrairement au bash, il faut mettre un seul backslash et utiliser des guillemets. Code couleur du texte
<code> black = \033[0;30m darkgray = \033[1;30m blue = \033[0;34m lightblue = \033[1;34m green = \033[0;32m lightgreen = \033[1;32m cyan = \033[0;36m lightcyan = \033[1;36m red = \033[0;31m lightred = \033[1;31m purple = \033[0;35m lightpurple = \033[1;35m brown = \033[0;33m yellow = \033[1;33m lightgray = \033[0;37m white = \033[1;37m </code> Code couleur du fond <code> black = \033[40m red = \033[41m green = \033[42m yellow = \033[43m blue = \033[44m magenta = \033[45m cyan = \033[46m lightgray = \033[47m </code> Toujours réinitialiser la fin de la phrase par \033[0m ===== Modifier le contenu d’un fichier avec sed ===== Il peut être utile d’utiliser sed pour modifier une valeur dans un fichier de configuration en tapant juste une ligne de commande. Autre page sur sed Dans mon cas, je voulais modifier une variable dans tous mes fichiers *awstats et donc au lieu d’ouvrir un à un mes fichiers de conf, j’ai juste eu à lancer la commande sed ;) Exemple pour modifier la variable Categories dans un fichier sed -i ‘s/^Categories=./Categories=toto/' FILENAME option -i de sed : écrire dans le fichier commande ‘s/A/B/' : remplacer A par B avec pour A : ^Categories=. : n’importe quelle ligne commençant (le ^) par Categories= et suivi par un nombre quelconque (*) de n’importe quel caractère (.) Une variante qui fait la même chose que sed mais en utilisant grep et echo grep ‘^Categories=' FILENAME || { echo; echo ‘Categories=toto’; } »FILENAME grep ‘^Categories=' FILENAME : cherche une ligne commençant par Categories= dans FILENAME si la commande échoue elle retourne un code d’erreur 1 et ce qui est après || est exécuté : { echo; echo ‘Categories=toto’; } »FILENAME : saute une ligne et ajoute (») ‘Categories=toto’ à FILENAME, ce qui aurait pu aussi être écrit : echo -e “\nCategories=toto” »FILENAME l’option -e autorise les caractères spéciaux tels que \n (newline) edit: et juste pour le fun (et le chipotage) il ne sert à rien de lancer la substitution si le motif Categories= est absent (dans le cas où on fait le grep) donc : <code> if grep -q ‘^Categories=' FILENAME; then sed -i ‘s/^Categories=.*/Categories=toto/' FILENAME else echo -e “\nCategories=toto” »FILENAME fi </code> grep -q pour ne pas avoir de sortie, juste le code de retour 0 (trouvé) ou 1 (absent) ===== trap, wait, sleep ===== trap sert à exécuter une commande lorsqu’un signal est envoyé au script en cours wait sert à attendre la fin d’une commande qui aura été lancé en tache de fond sleep sert à faire une pause suivant un nombre de seconde définit Le petit script suivant est une démonstration de wait, trap et sleep.
Le but est de lancer 3 commandes en parallèle et de vérifier l’état d’avancement en parallèle puis de récupérer le code de retour à la fin. - Au commencement, on exécute trois wget en tache de fond dont le 3ème est volontairement erroné - Je reviendrai sur trap plus tard - On fait une boucle while avec un test sur le rendu de la commande jobs qui ne renvoi rien quand il n’y a plus rien qui tourne en tache de fond. Donc, tant que les commandes précédentes lancées en tache de fond ne sont pas fini, on continu d’exécuter tout ce qui se trouve dans la boucle while - Dans la boucle, je fais une pause d’une seconde et j’affiche ensuite la taille du fichier que nous sommes en train de télécharger pour chaque tache qui tourne. - Lorsque toutes les taches ont fini de tourner, je récupère le code d’erreur avec wait et on affiche le résultat. <code bash>#!/bin/bash wget -q http://proof.ovh.net/files/10Mio.dat -O 10Mio.dat & PID1=$! wget -q http://proof.ovh.net/files/1Mio.dat -O 1Mio.dat & PID2=$! # plusieurs commandes passées en tache de fond ( echo blabla wget -q http://proof.ovh.net/files/1Mio.dat -O 1Mio.dat ) & PID3=$! trap ‘kill $PID1 $PID2; exit 0’ 1 2 3 15 while [ -n “jobs” ] do jobs if [ -d /proc/$PID1 ] then sleep 1 echo Process $PID1 du 10Mio.dat | cut -f1 fi if [ -d /proc/$PID2 ] then sleep 1 echo Process $PID2 du 1Mio.dat | cut -f1 fi done wait $PID1 exit1=$? wait $PID2 exit2=$? wait $PID3 exit3=$? echo “Process $PID1 : Code de retour $exit1” echo “Process $PID2 : Code de retour $exit2” echo “Process $PID3 : Code de retour $exit3” </code> A quoi sert le trap ? Lorsque je lance mon script et que je ne veux pas attendre la fin du téléchargement, je quitte en faisant un Ctrl+C. Le problème est que le wget continu de tourner en tache de fond et si je lance 10 fois mon script et que je fais 10 fois Ctrl+C je me retrouve avec 10 wget qui tournent en tache de fond. trap va me permettre de lancer une commande lorsque je fais un Ctrl+C ou un kill (mais pas un kill -9). Ici j’ai mis la commande kill $!. Souvenez-vous que $! correspond au pid de la commande lancé précédemment. Il ne faut pas oublier exit 0 sinon vous ne sortirez jamais du script avec votre Ctrl+C, vous serez obliger d’utiliser kill -9 ===== lien symbolique nommé selon la date de répertoire ===== Dans le cas d’un backup avec rsnapshot ou on a des dossiers de type daily.0, daily.1, daily.2 etc.. je voulais des noms de répertoire plus parlant comme par exemple la date de création du répertoire. for f in /media/hdd/backup/daily.* ; do ln -s $f ls -ld --time-style=+%Y-%m-%d $f | awk '{print $6}'; done
On obtient : <code bash> lrwxrwxrwx 1 root root 29 janv. 29 00:15 2014-01-16 → /media/hdd/backup/daily.12 lrwxrwxrwx 1 root root 29 janv. 29 00:15 2014-01-17 → /media/hdd/backup/daily.11 lrwxrwxrwx 1 root root 29 janv. 29 00:15 2014-01-18 → /media/hdd/backup/daily.10 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-19 → /media/hdd/backup/daily.9 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-20 → /media/hdd/backup/daily.8 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-21 → /media/hdd/backup/daily.7 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-22 → /media/hdd/backup/daily.6 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-23 → /media/hdd/backup/daily.5 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-24 → /media/hdd/backup/daily.4 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-25 → /media/hdd/backup/daily.3 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-26 → /media/hdd/backup/daily.2 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-27 → /media/hdd/backup/daily.1 lrwxrwxrwx 1 root root 28 janv. 29 00:15 2014-01-28 → /media/hdd/backup/daily.0 </code> Il n’y a plus qu’a faire pointer votre partage samba sur ce répertoire de lien symbolique ;)
===== Renommer / changer l’extension de plusieurs fichiers ===== Pour changer l’extension de tous les fichiers .css en .less rename ‘s/.css$/.less/' *.css
===== Couper un gros fichier en petit morceau ===== <code># split –help Utilisation : split [OPTION]… [INPUT [PREFIX]] Affiche sur la sortie des morceaux de INPUT de taille fixe selon PREFIXaa, PREFIXab, … ; par défaut la taille est de 1000 lignes et le préfixe par défaut est « x ». Sans INPUT ou quand INPUT est -, la lecture se fait sur l’entrée standard. Les arguments obligatoires pour les options longues le sont aussi pour les options courtes. -a, –suffix-length=N utilise les suffixes de longueur N (par défaut 2) -b, –bytes=BYTES écrit BYTES octets par fichier de sortie -C, –line-bytes=SIZE écrit au plus SIZE octets par ligne par fichier de sortie -d, –numeric-suffixes utilise des suffixes numériques et non alphabétiques -l, –lines=NUMBER écrit NUMBER lignes par fichier de sortie –verbose affiche un diagnostic juste avant chaque ouverture de fichier de sortie –help affiche l’aide et quitte –version affiche des informations de version et quitte SIZE peut être (ou un entier optionnellement suivi par) l’une des valeurs suivantes : kB 1000, K 1024, MB 10001000, M 10241024 et ainsi de suite pour G, T, P, E, Z et Y. </code> Pour découper un gros messages.log en plusieurs petits fichier nommé messages.split.00, messages.split.01… split -d -b 500MB messages.log messages.split. ===== Redimensionner des images ===== On a un répertoire plein d’image HD et on voudrait un répertoire miniature avec les images redimensionnées. Et bien sur, on ne veut pas recréer les miniatures qui existe déjà sauf si c’est voulu. En 1er lieu, installez le paquet imagemagick qui contient tout un tas d’outils de création, conversion d’images ( http://www.imagemagick.org/script/command-line-tools.php ) Si vous voulez tout convertir en une fois mogrify -resize 200 -quality 75 -interlace Plane -strip -path /home/user/photo/miniature /home/user/photo/*.jpg Sinon voici le script <code bash> #!/bin/bash pathsrc='/home/user/photo’ pathdest='/home/user/photo/miniature’ cd $pathsrc for file in *.jpg; do if [ ! -f $pathdest/$file -o “$1” == “overwrite” ]; then convert -resize 200 -quality 75 -interlace Plane -strip $file $path_dest/$file fi done </code> Ici on fait une boucle sur les fichiers avec un filtre sur les extensions jpg. Ensuite on teste si le fichier n’existe pas dans la destination OU si l’argument passé au script est “overwrite” alors on exécute la commande “convert” * -resize 200 permet de réduire l’image sur une largeur de 200px en gardant la proportionnalité de l’image * -quality 75 joue sur la compression de l’image et donc sa qualité. 0 renvoie une petite taille mais une image pourri, 100 renvoie une belle image mais d’une taille conséquente * -interlace Plane est le mode progressif du format jpeg qui permet sur les sites web d’afficher une 1er image en mode dégradé avant d’avoir fini son chargement complet * -strip permet de supprimer les informations inutiles de l’image ===== Manipuler les process ===== source : http://monkeypatch.me/blog/move-a-running-process-to-a-new-screen-shell.html Récupérer un process lancé sur un autre terminal avec la commande reptyr En bref * [Ctrl]+[C] : arrête le processus courant, càd que ça le kill… * [Ctrl]+[Z] : mets en arrière plan le processus courant, et rend la main (on se retrouve sous un shell) * bg : continue l’exécution en tache de fonds d’un programme qui s’est mangé un [Ctrl]+[Z] dans la gueule… * fg : continue l’exécution en avant plan (on perd le prompt shell) d’un programme qui s’est fait [Ctrl]+[Z]er… * jobs : liste les processus qui sont en arrière plan ===== Date de fichier ===== La commande touch permet de changer la date de modification d’un fichier <code># touch toto.txt # stat toto.txt File: « toto.txt » Size: 0 Blocks: 0 IO Block: 4096 fichier vide Device: fd00h/64768d Inode: 130793 Links: 1 Access: (0644/-rw-r–r–) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2016-07-04 08:47:38.715578195 +0000 Modify: 2016-07-04 08:47:38.715578195 +0000 Change: 2016-07-04 08:47:38.715578195 +0000 # touch -d “2015-01-01 00:00” toto.txt # stat toto.txt File: « toto.txt » Size: 0 Blocks: 0 IO Block: 4096 fichier vide Device: fd00h/64768d Inode: 130793 Links: 1 Access: (0644/-rw-r–r–) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2015-01-01 00:00:00.000000000 +0000 Modify: 2015-01-01 00:00:00.000000000 +0000 Change: 2016-07-04 08:48:40.464863103 +0000 On peut aussi utiliser la notation suivante # touch -d “-1 day” toto.txt </code> ===== rbash (restrited bash) ===== A creuser pour les accès restreint en ssh https://en.wikipedia.org/wiki/Restricted_shell ===== vérifier si le script tourne encore ===== Pour voir si le script abc.sh tourne encore, on peut utiliser le code suivant <code bash> if pidof -x “abc.sh” >/dev/null; then echo “Process already running” fi </code> Alternatively, have your script create a PID file when it executes. It’s then a simple exercise of checking for the presence of the PID file to determine if the process is already running. <code bash> #!/bin/bash # abc.sh mypidfile=/var/run/abc.sh.pid # Could add check for existence of mypidfile here if interlock is # needed in the shell script itself. # Ensure PID file is removed on program exit. trap “rm -f – ‘$mypidfile’” EXIT # Create a file with current PID to indicate that process is running. echo $$ > “$mypidfile” </code> … Update: The question has now changed to check from the script itself. In this case, we would expect to always see at least one abc.sh running. If there is more than one abc.sh, then we know that process is still running. I’d still suggest use of the pidof command which would return 2 PIDs if the process was already running. You could use grep to filter out the current PID, loop in the shell or even revert to just counting PIDs with wc to detect multiple processes. Here’s an example: <code bash> #!/bin/bash for pid in $(pidof -x abc.sh); do if [ $pid != $$ ]; then echo “[$(date)] : abc.sh : Process is already running with PID $pid” exit 1 fi done </code> Optimisation, comme on sait que le nom du script est le notre, on peut écrire <code bash> for pid in $(pidof -x $0); do if [ $pid != $$ ]; then echo “[$(date)] : $0 : Process is already running with PID $pid” exit 1 fi done </code> Très utile quand on lance un script toutes les minutes pour éviter de se retrouver avec 500 process qui tournent en même dans le cas ou la réponse du script dépasserait la minute ===== ls et le globbing (ou filtrage avancé) ===== <code bash> bash$ ls -l total 2 -rw-rw-r– 1 bozo bozo 0 Aug 6 18:42 a.1 -rw-rw-r– 1 bozo bozo 0 Aug 6 18:42 b.1 -rw-rw-r– 1 bozo bozo 0 Aug 6 18:42 c.1 -rw-rw-r– 1 bozo bozo 466 Aug 6 17:48 t2.sh -rw-rw-r– 1 bozo bozo 758 Jul 30 09:02 test1.txt bash$ ls -l t?.sh -rw-rw-r– 1 bozo bozo 466 Aug 6 17:48 t2.sh bash$ ls -l [ab]* -rw-rw-r– 1 bozo bozo 0 Aug 6 18:42 a.1 -rw-rw-r– 1 bozo bozo 0 Aug 6 18:42 b.1 bash$ ls -l [a-c]* -rw-rw-r– 1 bozo bozo 0 Aug 6 18:42 a.1 -rw-rw-r– 1 bozo bozo 0 Aug 6 18:42 b.1 -rw-rw-r– 1 bozo bozo 0 Aug 6 18:42 c.1 bash$ ls -l [^ab]* -rw-rw-r– 1 bozo bozo 0 Aug 6 18:42 c.1 -rw-rw-r– 1 bozo bozo 466 Aug 6 17:48 t2.sh -rw-rw-r– 1 bozo bozo 758 Jul 30 09:02 test1.txt bash$ ls -l {b,c,est} -rw-rw-r– 1 bozo bozo 0 Aug 6 18:42 b.1 -rw-rw-r– 1 bozo bozo 0 Aug 6 18:42 c.1 -rw-rw-r– 1 bozo bozo 758 Jul 30 09:02 test1.txt </code> source: http://tldp.org/LDP/abs/html/globbingref.html ===== Problème d’affichage sur la ligne du prompt ===== Avec certain prompt fantaisiste, il peut y avoir des problème d’affichage notamment quand on remonte dans l’historique des commandes, ça peut vite devenir illisible. D’où l’importance d’entourer vos codes couleurs dans la variable PS1 par [ et ] Si vous appelez une fonction dans la variable PS1, il faudra entourer le code couleur par \001 et \002 (voir le code dans le chapitre suivant) source: http://mywiki.wooledge.org/BashFAQ/053 Mots clés pour recherche sur le web: Line wrapping issues in Bash ===== Afficher le status de la dernière commande dans le prompt ===== Ajoutez dans votre .bashrc ce petit bout de code <code bash> getexitstatus(){ es=$? if [ $es -eq 0 ] then echo -e ‘\001\033[0;32m\002✔\001\033[0;0m\002’ else echo -e ‘\001\033[0;31m\002✘ ‘$es’\001\033[0;0m\002’ fi } PS1=‘$(getexitstatus) [\033[1;34m]\u:[\033[0;36m]\W[\033[0;0m] $ ' </code>

linux/bash.txt · Dernière modification : de edmc73