commandes diverses
Récupérer les attributs d'un fichier
$ stat -c "%a" file # droits
$ stat -c "%U:%G" file # propriétaire:groupe
$ stat -c "%x" file # dernier accès
$ stat -c "%U:%G" file # propriétaire:groupe
$ stat -c "%x" file # dernier accès
Trouver les 10 lignes les plus répétées dans un fichier
$ sort | uniq -c | sort -nr | head
Alerter par un beep quand une commande se termine
$ ./mycommand ; echo -ne "a"
Avertir quand une commande s'est mal terminée
$ ./mycommand || echo "Ca ne va pas"
Avertir quand une commande s'est bien terminée
$ ./mycommand && echo "Ca va bien"
Les 2 à la fois (attention à l'ordre)
$ ./mycommand && echo "Ca va bien" || echo "Ca ne va pas"
Compter des lignes sans avoir le nom de fichier dans la sortie
$ wc -l < file
Récupérer les 3 lignes suivant une expression
$ grep -A3 "^#"
Récupérer les 3 lignes précédant une expression
$ grep -B3 "---"
Récupérer les lignes entre 2 expressions
$ sed -n '/Location/,//Location/p'
Imprimer un fichier en commençant par la dernière ligne
$ tac fichier
Imprimer un fichier en en commençant par la fin de chaque ligne
$ rev fichier
Grepper des lignes sur un critère numérique
$ grep "^([0-9]|[0-9]{2}|1([01][0-9]|2[012])) " file # difficile
$ while read a b; do [ $a -lt 123 ] && echo "$a $b"; done < file # facile
$ while read a b; do [ $a -lt 123 ] && echo "$a $b"; done < file # facile
Problème avec votre terminal ? S'il devient illisible suite à une commande, à l'aveugle tapez :
$ reset
Besoin de caractères spéciaux avec echo ? Option -e :
$ echo -e "t:n"
Problèmes sur un lien IP ? Testez rapidement et approximativement un taux de perte :
$ ping -f destinataire
Besoin de mettre en évidence les expressions matchées avec grep ? Mettez les en couleur (gardez le en alias, par défaut il ne met pas de couleur dans les | ).
$ grep --color pattern fichier
$ alias grep="grep --color"
$ alias grep="grep --color"
Même chose mais utilisable dans un less
$ grep --color=always pattern fichier | less -r
Une dernière astuce, pensez toujours à créer un fichier prêt à être supprimé en cas de dépassement de capacité de partition, le temps de faire un vrai ménage. Cela peut par exemple éviter de casser un serveur mysql. Les partitions sensibles à ces problèmes sont principalement celles de /var
$ dd if=/dev/zero of=/var/lib/FUSIBLE bs=1M count=10 # 10 Mo
$ dd if=/dev/zero of=/var/log/FUSIBLE bs=1M count=10 # 10 Mo
$ dd if=/dev/zero of=/var/log/FUSIBLE bs=1M count=10 # 10 Mo
Commenter des lignes comme en sed :
$ sed 's/^/#/'
$ perl -pe 's/^/#/'
$ perl -pe 's/^/#/'
Formater des lignes comme en awk :
$ awk '{print "$1:$3"}'
$ perl -ne 'split; print "$_[0]:$_[2]n"'
$ perl -ne 'split; print "$_[0]:$_[2]n"'
Sélectionner des lignes comme en grep :
$ grep "^[0-9]"
$ perl -ne 'print if /^[0-9]/'
$ perl -ne 'print if /^[0-9]/'
Perl dispose de l'option -i comme sed. Cette option permet d'éditer les fichiers en ligne. Si un mot est ajouté après -i, le fichier sera sauvegardé.
$ perl -i.bak -pe '$i++; s/^/$i /' file # numérote les lignes du fichier
Tout comme awk, perl supporte l'exécution de code au début et à la fin de la boucle :
# Implémentation de head en perl
$ perl -ne 'BEGIN{$i=10}{print if $i-->0}'
$ perl -ne 'BEGIN{$i=10}{print if $i-->0}'
# Implémentation de wc -l en perl
$ perl -ne '{$i++}END{print "$in"}'
$ perl -ne '{$i++}END{print "$in"}'
L'avantage d'utiliser perl est que le jour ou vous voulez faire grossir votre script, c'est très simple.
perl -pe '...' -> while(<>) { ... ; print }
perl -ne '...' -> while(<>) { ... }
Par exemple faisons grossir notre wc pour afficher un peu plus (dans un fichier) :
#!/usr/bin/perl
$char=0;
$word=0;
$line=0;
while(<>)
{
$char += length;
split;
$word += scalar @_;
$line++;
}
print "$line $word $charn";
$char=0;
$word=0;
$line=0;
while(<>)
{
$char += length;
split;
$word += scalar @_;
$line++;
}
print "$line $word $charn";
Faisons un test :
$ PS1=youpi
Mais revenons à quelque chose de plus standard :
$ PS1="u@h:w$ "
Vous aurez compris que les * représentent des valeurs interprétées par le shell. Utilisons-en quelques unes sympathiques.
Si vous voulez être avertis par un bip à chaque nouvelle ligne (cela vous indique que la commande précédente vient de se terminer), précédez le de a.
$ PS1="au@h:w$ "
Si vous pensez que votre shell n'est pas assez aéré, ajoutez un retour à la ligne :
$ PS1="u@h:w$n"
Vous pouvez aussi intégrer l'heure à votre prompt, cela peut être utile pour estimer la durée de vos commandes :
$ PS1="[t] u@h:w$ "
Si vous utilisez souvent l'historique de bash avec les numéros de ligne vous pourriez afficher ces numéros de ligne :
$ PS1="! u@h:w$ "
Ainsi, utilisez !1234 pour répéter la commande de la ligne 1234.
Si vous voulez juste les numéros de commande sans utiliser l'historique, utilisez plutôt # que !
Et finissons par le plus beau, les couleurs. Le caractère e est le caractère d'échappement qui précède un code ANSI. Les codes ANSI permettent de formater un texte dans un terminal. Exemple pour afficher le nom de machine en vert :
$ PS1="u@h:e[01;32mwe[00m$ "
Pour une documentation plus complète sur les codes ANSI lisez cette page.
Mais attention, un tel prompt vous poserait quelques problèmes d'affichage car bash calcule la taille des lignes pour les afficher proprement. Vous devez donc entourer tous vos codes non affichables de [ et ] ce qui donne :
$ PS1="u@h:[e[01;32m]w[e[00m]$ "
Et enfin vous pouvez utiliser toutes les substitutions et variables que supporte bash pour formater votre prompt.
Il n'existe pas que PS1, mais aussi PS2, PS3 et PS4 qui ont un peu moins d'intérêt à être personnalisés.
- PS2 sert lorsque votre ligne n'est pas terminée, par exemple lorsqu'elle contient une chaine de caractère non terminée
- PS3 sert de prompt pour la commande select d'usage assez rare
- PS4 sert de base pour l'affichage des traces de debug de script (commande set -x)
Et enfin pour pérenniser votre personnalisation, n'oubliez pas d'écrire votre ligne dans le fichier ~/.bashrc
PS: pour le détail des caractères interprétés, man 1 bash puis /^PROMPTING
Supposons que vous ayez 2 listes. Par exemple la liste des courses et la liste des produits achetés. Il vous est possible de récupérer la liste des éléments communs grâce à la méthode suivante :
$ sort liste1 > liste1.tmp
$ sort liste2 > liste2.tmp
$ comm -1 -2 liste1.tmp liste2.tmp
$ sort liste2 > liste2.tmp
$ comm -1 -2 liste1.tmp liste2.tmp
- on fait un sort car comm ne fonctionne que sur des fichiers dont les lignes sont ordonnées de la même façon
- -1 et -2 indiquent de ne pas garder les lignes uniques au fichier 1 ou au fichier 2
Notez que si vous aviez plusieurs fois les mêmes lignes dans vos fichiers, il se peut que vous vouliez ne comparer que des lignes différentes (ne pas compter le sel comme non acheté s'il est écrit 2 fois dans la liste des courses par exemple). Dans ce cas vous utiilserez les commandes suivantes :
$ sort liste1 | uniq > liste1.tmp
$ sort liste2 | uniq > liste2.tmp
$ sort liste2 | uniq > liste2.tmp
Toujours en utilisant comm, vous pouvez obtenir les éléments présents dans la liste 1 et pas dans la liste 2. Il vous faut alors utiliser les options "-2 -3".
Sans options comm affiche les données sur 3 colonnes :
$ comm liste1.tmp liste2.tmp
Ceci permet de comparer les fichiers en affichant sur la première colonne les données uniques au fichier 1, sur la 2e les données uniques au fichier 2 et sur la 3e les données communes.
Notez que pour une comparaison visuelle des 2 fichiers (mais plus difficilement scriptable cette fois), la commande diff est plus adaptée :
$ diff -y liste1.tmp liste2.tmp
On a alors les 2 fichiers affichés sur 2 colonnes et un petit caractère > ou < indique si la ligne n'apparaît que sur un des 2 fichiers.
Supposons que vous ayez un gros fichier et que vous vouliez récupérer les lignes 200 à 235. Votre premier réflexe sera surement :
$ head -n 235 file.txt | tail -n 35
Oui, mais en pratique cela revient a faire lire le fichier par 2 processus, ce qui pour un gros fichier peut être particulièrement consommateur de ressources. Utilisez plutôt la commande suivante qui fait le tout en une seule passe (et qui vous évitera de faire une soustraction) :
$ sed -n '200,235p' file.txt
Oui, mais vous aimeriez bien ne pas avoir à mesurer les numéros des lignes que vous voulez récupérer. Qu'à cela ne tienne, vous pouvez utiliser autre chose que des numéros de ligne pour l'extraction. Par exemple des expressions régulières :
$ sed -n '/^Begin/,/^End/p' file.txt
Vous pouvez aussi faire le contraire, c'est-à-dire supprimer des lignes plutôt que de les sélectionner :
$ sed '/^Begin/,/^End/d' file.txt
Et cerise sur le gâteau, vous pouvez appliquer une expression de substitution uniquement aux lignes concernées :
$ sed '/^Begin/,/^End/s/search.*/replace/' file.txt
Publicité