Domaine public 🅭

CMS minimal
ecrit avec VI

[ /  ^ < ]

www.memoperso.fr/linux/shell/presentation/exemples

commenter       14/12/2020
timeout       12/01/2023
watch       11/01/2023
lire chaque octet      05/02/2021
archiver par courriel      24/07/2024
planquer un zip      24/07/2024
afficher ascii       24/07/2024
captcha       24/07/2024
afficher unicode html      03/07/2020
asciidoc+graphviz       20/07/2020
prepare chroot       22/07/2020
synchroniser       22/07/2024
boucler commande       13/05/2024
octets absents       21/08/2023
recurence       25/07/2024

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>"

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

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