Domaine public 🅭

CMS minimal
ecrit avec VI

[ /  ^ < ]

ludrivia.n-f.fr/linux/shell/presentation/exemples

commenter       05/06/2026
timeout       12/01/2023
watch       11/01/2023
lire chaque octet      05/02/2021
archiver par courriel      05/06/2026
planquer un zip      05/06/2026
afficher ascii       05/06/2026
captcha       05/06/2026
afficher unicode html      05/06/2026
asciidoc+graphviz       05/06/2026
prepare chroot       22/07/2020
synchroniser       22/07/2024
boucler commande       13/05/2024
octets absents       05/06/2026
recurence       25/07/2024
changer de groupe      29/04/2026

Comme en python ou autre, les commentaires commencent par un # à ne pas confondre avec 
en première ligne avec un #! pour dire explicitement quel programme va executer le script
(sinon c'est le shell courrant qui sert)
#!/bin/bash pour commenter toute une partie utiliser la commande nulle ":" :<<SAUTER c'est tout bête mais je n'avais pas trouvé tout seul . . . SAUTER

# "timeout" impose un délais d'execution à une commande evitant qu'un script bloque

# si la commande se termine avant le delais, transmet le code retour, sinon 124

# exemple si on veut prevoir l'éventualité d'une entrée standard:

timeout 1 cat > $(mktemp)

# malheureusement elle n'existe pas sur certains vieux systèmes
export TMOUT=1
# cat | while read i; do echo "$i"; done >  $(mktemp)
while read i; do echo "$i"; done >  $(mktemp)

# si ça non plus n'existe pas
cat & sleep 1; kill $!

# "watch" lance en boucle une commande

watch -n 60 date # 2 par defaut

watch -g ping -c 1 site.en.panne.hs # arrete quand la valeur change

watch -d ifconfig # surligne les differences

# pour lire/ecrir un fichier à l'octet

od -An -vto1 -w1 | while read i; do echo -ne "\0$i"; done

# ou en exa remplacer -vto1 par -vtx1  plus simple utiliser xxd et inverser

xxd -p -c1 | tac |  while read i; do echo -ne "\x$i"; done

# attention aux accents sur deux caractères entre
c380 pour À et c3bf pour ÿ voir tableau

#!/bin/bash # archivage par courriel d un repertoire en parametre ## à faire : gérer les noms de repertoires contenant des espaces # commandes prerequises : md5sum mutt gzip tar find cmp diff mv # commande optionelle pour contrer l alergie au format zip : uuencode # ou gpg -a qui en plus chiffre # pour eviter le reenvoi d une archive identique il faut conserver la signature des fichiers individuellement car le resultat de gzip nest pas constant DEST=toto@courriel.fr DATE=$(date +%Y_%m_%d_%Hh%M) test "$1" || exec echo "$0 : demande un repertoire en parametre" >&2 test -d "$1" || exec echo "$0 : ne trouve pas le reperoite $1" >&2 REP=$1 SUJET="archivage $REP sur $HOSTNAME" SIGN=sig-$(tr / - <<< $REP).$(cat $0 | md5sum | tr -d \ -) # contenant les signatures des fichiers du repertoire ARCH=/tmp/ar.$(basename $REP).$DATE cd $(dirname $REP) test -f $REP/$SIGN && mv $REP/$SIGN /tmp/$SIGN-1.$$ rm -f $REP/$SIGN find $(basename $REP) -type f -exec md5sum {} \; > $REP/$SIGN cmp /tmp/$SIGN-1.$$ $REP/$SIGN > /dev/null 2>&1 && exec echo "$0 rien de different, aucune archive envoyée" >&2 PJ=$ARCH.tgz tar czf $PJ $(basename $REP) # uuencode $PJ $PJ > $PJ.uu; PJ=$PJ.uu # gpg -ae -r 82440BECE5F590F7 $PJ; PJ=$PJ.asc diff $REP/$SIGN /tmp/$SIGN-1.$$ 2> /dev/null | mutt -s "$SUJET" $DEST -a $PJ

#!/bin/bash # planquer un fichier ZIP # certains serveurs de courriels bloquent stupidement les pièces jointes # comme c est un format par accumulation # le fichier est lu par la fin # il suffit donc de coller une image devant pour tromper son monde test "$1" || exec "echo $0 : il faut mettre un fichier en parametre" test -f "$1" || exec "echo $0 : $1 n'est pas un fichier" echo -ne "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52" > "$1".png echo -ne "\x00\x00\x00\x05\x00\x00\x00\x05\x01\x03\x00\x00\x00\xb7\xa1\xb4" >> "$1".png echo -ne "\xa6\x00\x00\x00\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61" >> "$1".png echo -ne "\x05\x00\x00\x00\x20\x63\x48\x52\x4d\x00\x00\x7a\x26\x00\x00\x80" >> "$1".png echo -ne "\x84\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00\x75\x30\x00\x00\xea" >> "$1".png echo -ne "\x60\x00\x00\x3a\x98\x00\x00\x17\x70\x9c\xba\x51\x3c\x00\x00\x00" >> "$1".png echo -ne "\x06\x50\x4c\x54\x45\xff\xff\xe0\xff\xff\xff\x5d\x06\xb2\xa5\x00" >> "$1".png echo -ne "\x00\x00\x01\x62\x4b\x47\x44\x01\xff\x02\x2d\xde\x00\x00\x00\x09" >> "$1".png echo -ne "\x6f\x46\x46\x73\x00\x00\x05\x68\x00\x00\x02\xa6\x00\x97\x6c\xdb" >> "$1".png echo -ne "\x5f\x00\x00\x00\x09\x76\x70\x41\x67\x00\x00\x07\x80\x00\x00\x04" >> "$1".png echo -ne "\xb0\x00\x2d\x09\x91\x3b\x00\x00\x00\x0b\x49\x44\x41\x54\x08\xd7" >> "$1".png echo -ne "\x63\x60\x80\x01\x00\x00\x0a\x00\x01\xe7\xf8\xda\xfa\x00\x00\x00" >> "$1".png echo -ne "\x00\x49\x45\x4e\x44\xae\x42\x60\x82" >> "$1".png # plus court si on a installé base64 # base64 -d <<< iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFAQMAAAC3obSmAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABlBMVEX//+D///9dBrKlAAAAAWJLR0QB/wIt3gAAAAlvRkZzAAAFaAAAAqYAl2zbXwAAAAl2cEFnAAAHgAAABLAALQmROwAAAAtJREFUCNdjYIABAAAKAAHn+Nr6AAAAAElFTkSuQmCC > "$1".png cat "$1" >> "$1".png echo "$0 : le fichier $1.png a ete cree" >&2

#!/bin/bash # affiche les codes ASCII echo " 0123456789ABCDEF" for i in {2..9} {A..F} do echo -n "$i "; for j in {0..9} {A..F} do echo -en "\x$i$j" done echo done

#!/bin/sh # transforme en une image brouillée genre CAPTCHA test "$1" || exec echo "$0 : il faut un mot en parametre" FT=$(mktemp) convert -pointsize 50 label:"\ $* " png:$FT seq 6 | while read i; do convert $FT +noise Impulse $FT; done echo fichier $FT display $FT #!/bin/sh # transforme un fichier texte en image brouillée TT=$(mktemp) FT=$(mktemp) convert -pointsize 50 label:"\ " png:$TT cat | while read i; do convert -pointsize 50 label:"\ $i " png:$FT convert $TT $FT -append $TT done seq 6 | while read i; do convert $TT +noise Impulse $TT; done echo fichier $TT display $TT

#!/bin/bash # tableau Unicode en HTML TITRE="Unicode" : les 2<sup>17</sup> premiers caract&egrave;res" fonction_ligne() { echo "<tr>" for i in "" {0..255}; do echo "<td>$i" done } echo "<html>" echo "<head><title>$TITRE</title></head>" echo "<body>" echo "<h1>$TITRE</h1>" echo "<table border>" fonction_ligne for i in $(eval echo {0..$((2**17 - 1))}); do test $(($i % 256)) = 0 && echo "<tr><td>$(($i / 256))" echo "<td>&#$i;" done fonction_ligne echo "</table>" echo "</body>" echo "</html>"

# "extention" pour asciidoc # sans besoin de fichier annexe pour les illustrations # exemple avec la commande dot de graphviz ou lilypond # ces extentions existent deja mais produisent un fichier PNG tributaire ( en fait l'option -a data-uri règle lde pb ) # commande base64 prérequise sinon en python3 # les lignes qui commencent par graphviz sont traitées à part # et mises comme une images à l'interieure de la future page HTML MOTCLE=lilypond #MOTCLE=graphviz ENTETE="echo '<img src=\"data:image/png;base64,'" COMMANDE="lilypond -dbackend=eps -dno-gs-load-fonts -dinclude-eps-fonts --png /tmp/\"\$FICHIER\".$$.ext; cat /tmp/\"\$FICHIER\".$$.png" #COMMANDE="dot -Tpng /tmp/\"\$FICHIER\".$$.ext" ALLER=" | base64 | sed -e 's!/!_-slash-_!g' -e 's/+/_-plus-_/g'" PIED="echo '\" alt=\"texte à la place\" title=\"titre\" border=\"0\">'" RETOUR=" | sed -e 's!_-slash-_!/!g' -e 's/_-plus-_/+/g'" test "$1" || exec "echo $0 : il faut mettre un fichier en parametre" test "$1" = "-" || test -f "$1" || exec "echo $0 : $1 n'est pas un fichier" if test "$1" = "-"; then REP=/tmp FICHIER=asciidoc+grapghviz.$$ else REP=$(dirname "$1") FICHIER=$(basename "$1" .txt) fi EXTENTION=0 sed 's/\\/\\\\/g' "$1" | while read i; do if test "$i" = "[$MOTCLE]"; then EXTENTION=1 > /tmp/"$FICHIER".$$.ext test "$MOTCLE" = lilypond && echo "\\paper{ oddFooterMarkup=##f }" > /tmp/"$FICHIER".$$.ext else if test "$(expr "$i" : '\(....\).*')" = "----"; then EXTENTION=$(( ($EXTENTION*2)%4 )) if test "$EXTENTION" = 2; then echo echo "++++" echo eval $ENTETE else # commande par exemple eval $COMMANDE $ALLER eval $PIED echo echo "++++" echo fi else if test "$EXTENTION" = 2; then echo $i >> /tmp/"$FICHIER".$$.ext else test "$EXTENTION" = 0 && echo "$i" fi fi fi done > /tmp/"$FICHIER".$$.txt asciidoc /tmp/"$FICHIER".$$.txt eval cat /tmp/"$FICHIER".$$.html $RETOUR > "$REP/$FICHIER.html" test "$1" = "-" && cat "$REP/$FICHIER.html" rm /tmp/"$FICHIER".$$.*

#! /bin/bash
# prépare le repertoire en parametre pour chroot

REPROOT="$1"
COMMANDES="bash ls cat rm nc date hostname env file find less id chown chgrp"

test "$REPROOT" || exec echo "$0 : attend un repertoire en parametre"
test -d "$REPROOT" || exec echo "$0 : $REPROOT n'est pas un parametre"
cd $REPROOT
mkdir -p {bin,lib,lib64,usr/bin,tmp}
for i in $COMMANDES
do
	C=$(type -p $i)
	cp $C ./$C
	ldd $C | egrep -o '/lib.*\.[0-9]'
done | sort -u | while read i
do
	if test -f $i
	then
		test -d ./$(dirname $i) || mkdir -p ./$(dirname $i)
		cp $i ./$i
	fi
done

# pour synchroniser l'execution de deux programmes:


# à l'avance
mknod /tmp/pipe p

# dans une première fenêtre
echo "j'attends";cat /tmp/pipe; echo "j'ai fini"


# dans une autre fenêtre:
echo "vas-y" > /tmp/pipe; echo "enfin"

# ça marche aussi en inversant l'ordre



# entre deux machines en réseau local mais il faut installer socket

# sur le serveur qui attend
socket -s XXXXX    # n° de port de plus de 10000 si non root -l si on veut que ça ne s'arrête pas

# sur le client
socket -q adresse_serveur XXXXX      # -q pour arrêter en fin de saisie
.
.
[Ctrl] D


# plus universel avec la commande nc qui est partout il faut utiliser exactement la même adresse

# sur le serveur qui attend
nc -lp port

# sur le client
nc adresse port


# basic pour commande qui ne reponds pas
until timeout 10 commande; do date; done

# exemple avec la commande vuze qui plante souvent
until read -t 5 -p "[Entrée] pour arrêter" REP; do date >> /tmp/vuze$$; vuze; kdialog --sorry "reprise $(cat /tmp/vuze$$ | wc -l)" & done; cat /tmp/vuze$$

# on a 10 secondes pour cliquer sur la vache si on veut arrêter le programme
timeout 10 /usr/games/xcowsay -t 11  "on sort ?" && exit

# liste les octets absents d'un fichier
#!/bin/bash (for i in {0..3}{0..7}{0..7}; do echo " $i"; done; od -vto1 -An -w1 nom_de_fichier) | sort | uniq -c | awk '$1 == 1 {print $2}' | while read i; do echo -e "$i \0$i"; done

# factorielle recursive jusqu a 20!
ffact () {
if test "$1" -gt 1
then echo $(($1 * $(ffact $(($1 - 1)))))
else echo 1
fi
}

# plus simple:
$(($(seq -s \* $1)))

# la commande newgrp est obligée de lancer un sous shell
# pour forcer le group dans l'usage d'une application
SHELL=/chemin/commande exec newgrp toto
# ou plus simple
exec sg toto commande

ƒraηcois✉memoρersο.ƒr