Outils pour utilisateurs

Outils du site


Panneau latéral

linux:bash (lu 74328 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.

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

Demander de saisir un texte

echo Hello, who am I talking to?
read varname
echo It\'s nice to meet you $varname

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
       \\     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)

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

[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

Ecrire en couleur

!/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!!.."

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

	black        = \033[0;30m
	dark_gray    = \033[1;30m
	blue         = \033[0;34m
	light_blue   = \033[1;34m
	green        = \033[0;32m
	light_green  = \033[1;32m
	cyan         = \033[0;36m
	light_cyan   = \033[1;36m
	red          = \033[0;31m
	light_red    = \033[1;31m
	purple       = \033[0;35m
	light_purple = \033[1;35m
	brown        = \033[0;33m
	yellow       = \033[1;33m
	light_gray   = \033[0;37m
	white        = \033[1;37m

Code couleur du fond

	black        = \033[40m
	red          = \033[41m
	green        = \033[42m
	yellow       = \033[43m
	blue         = \033[44m
	magenta      = \033[45m
	cyan         = \033[46m
	light_gray   = \033[47m

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 :

if grep -q '^Categories=' FILENAME; then
    sed -i 's/^Categories=.*/Categories=toto/' FILENAME
else
    echo -e "\nCategories=toto" >>FILENAME
fi

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.

  1. Au commencement, on exécute trois wget en tache de fond dont le 3ème est volontairement erroné
  2. Je reviendrai sur trap plus tard
  3. 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
  4. 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.
  5. Lorsque toutes les taches ont fini de tourner, je récupère le code d’erreur avec wait et on affiche le résultat.
#!/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"

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 :

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

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

# 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 1000*1000, M 1024*1024 et ainsi de suite pour
G, T, P, E, Z et Y.

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

#!/bin/bash
path_src='/home/user/photo'
path_dest='/home/user/photo/miniature'
 
cd $path_src
for file in *.jpg;
do
  if [ ! -f $path_dest/$file -o "$1" == "overwrite" ]; then
    convert -resize 200 -quality 75 -interlace Plane -strip $file $path_dest/$file
  fi
done

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

# 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

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

if pidof -x "abc.sh" >/dev/null; then
    echo "Process already running"
fi

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.

#!/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"

… 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:

#!/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

Optimisation, comme on sait que le nom du script est le notre, on peut écrire

for pid in $(pidof -x $0); do
    if [ $pid != $$ ]; then
        echo "[$(date)] : $0 : Process is already running with PID $pid"
        exit 1
    fi
done

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é)

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

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

get_exit_status(){
  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='$(get_exit_status) \[\033[1;34m\]\u:\[\033[0;36m\]\W\[\033[0;0m\] $ '
linux/bash.txt · Dernière modification: 07-05-2023 20:38 de edmc73