web-dev-qa-db-fra.com

Fonctionnalités cachées de Bash

Les scripts shell sont souvent utilisés comme colle, pour l'automatisation et les tâches ponctuelles simples. Quelles sont certaines de vos fonctionnalités "cachées" préférées du Bash Shell/langage de script?

  • Une fonctionnalité par réponse
  • Donnez un exemple et une brève description de la fonction, pas seulement un lien vers la documentation
  • Étiqueter l'entité en utilisant le titre en gras comme première ligne

Voir également:

72
Patrick

insérer le dernier paramètre de la ligne précédente

alt-. la combinaison de touches la plus utile de tous les temps, essayez-la et voyez, pour une raison quelconque, personne ne la connaît.

appuyez encore et encore pour sélectionner les derniers paramètres les plus anciens.

génial quand vous voulez faire autre chose à quelque chose que vous avez utilisé il y a un instant.

69
chillitom

Si vous souhaitez continuer à exécuter un processus après votre déconnexion:

disown -h <pid>

est un bash utile intégré. Contrairement à Nohup, vous pouvez exécuter disown sur un processus déjà en cours d'exécution.

Tout d'abord, arrêtez votre travail avec control-Z, obtenez le pid de ps (ou utilisez echo $!), utilisez bg pour l'envoyer en arrière-plan, puis utilisez disown avec l'indicateur -h.

N'oubliez pas d'arrière-plan votre travail ou il sera tué lorsque vous vous déconnecterez.

40
Alex Reynolds

Presque tout ce qui est répertorié dans la section EXPANSION du manuel

En particulier, l'expansion des paramètres:

$ I=foobar
$ echo ${I/oo/aa} #replacement
faabar
$ echo ${I:1:2}   #substring
oo
$ echo ${I%bar}   #trailing substitution
foo
$ echo ${I#foo}   #leading substitution
bar
38
Vinko Vrsalovic

Mon préféré:

Sudo !!

Réexécutez la commande précédente avec Sudo.

35
GloryFish

Plus de combinaisons de touches magiques:

  • Ctrl + r commence une "recherche incrémentielle inversée" dans l'historique de vos commandes. Au fur et à mesure que vous tapez, il récupère la commande la plus récente qui contient tout le texte que vous entrez.

  • Tab complète le mot que vous avez tapé jusqu'à présent s'il n'est pas ambigu.

  • TabTab répertorie toutes les réalisations pour le mot que vous avez tapé jusqu'à présent.

  • Alt + * insère toutes les complétions possibles, ce qui est particulièrement utile, par exemple, si vous venez de saisir une commande potentiellement destructrice avec des caractères génériques:

    rm -r source/d*.c Alt + *
    rm -r source/delete_me.c source/do_not_delete_me.c

  • Ctrl + Alt + e effectue l'alias, l'historique et l'expansion de Shell sur la ligne actuelle. En d'autres termes, la ligne actuelle est ré-affichée car elle sera traitée par le Shell:

    ls $HOME/tmp CtrlAlt + e
    ls -N --color=tty -T 0 /home/cramey

27
Adam Liss

Récupérer l'historique des commandes et des arguments

Il est possible d'accéder sélectivement aux commandes et arguments précédents en utilisant le ! opérateur. C'est très utile lorsque vous travaillez avec de longs chemins.

Vous pouvez vérifier vos dernières commandes avec history.

Vous pouvez utiliser les commandes précédentes avec !<n> étant n l'index de la commande dans history, les nombres négatifs comptent à rebours depuis la dernière commande de l'historique.

ls -l foo bar
touch foo bar
!-2

Vous pouvez utiliser les arguments précédents avec !:<n>, zéro est la commande,> = 1 sont les arguments.

ls -l foo
touch !:2
cp !:1 bar

Et vous pouvez combiner les deux avec !<n>:<m>

touch foo bar
ls -l !:1 !:2
rm !-2:1 !-2:2
!-2

Vous pouvez également utiliser des plages d'arguments !<n>:<x>-<y>

touch boo far
ls -l !:1-2

Autre ! les modificateurs spéciaux sont:

  • * pour tous les arguments

    ls -l foo bar
    ls !*
    
  • ^ pour le premier argument (!:1 == !^)

  • $ pour le dernier argument

    ls -l foo bar
    cat !$ > /dev/null
    
24
Jaime Soriano

J'aime la fonction -x, qui permet de voir ce qui se passe dans votre script.

bash -x script.sh 
20
stephanea

SECONDS=0; sleep 5 ; echo "that took approximately $SECONDS seconds"

SECONDES

Chaque fois que ce paramètre est référencé, le nombre de secondes écoulées depuis l'appel du shell est renvoyé. Si une valeur est affectée à SECONDS, la valeur renvoyée lors des références suivantes est le nombre de secondes écoulées depuis l'affectation plus la valeur affectée. Si SECONDS n'est pas défini, il perd ses propriétés spéciales, même s'il est réinitialisé par la suite.

19
Alberto Zaccagni

Voici l'un de mes favoris. Cela définit l'achèvement de l'onglet pour ne pas respecter la casse. C'est vraiment génial pour taper rapidement des chemins de répertoire, en particulier sur un Mac où le système de fichiers n'est pas sensible à la casse par défaut. Je mets ça dans .inputrc dans mon dossier personnel.

set completion-ignore-case on
17
danieljimenez

La variable spéciale aléatoire:

if [[ $(($RANDOM % 6)) = 0 ]]
    then echo "BANG"
else
    echo "Try again"
fi   
16
Vinko Vrsalovic

CtrlxCtrle

Cela chargera la commande actuelle dans l'éditeur défini dans la variable VISUAL. C'est vraiment utile pour les commandes longues comme certaines de celles listées ici.

Pour utiliser vi comme éditeur:

export VISUAL=vi
13
Robin

Gestion des expressions régulières

Les versions récentes de bash proposent une correspondance d'expressions régulières, vous pouvez donc:

if [[ "mystring" =~ REGEX ]] ; then  
    echo match
fi

où REGEX est une expression régulière brute au format décrit par man re_format.

Les correspondances de toutes les parties entre crochets sont stockées dans le tableau BASH_REMATCH, en commençant à l'élément 1 (l'élément 0 est la chaîne correspondante dans son intégralité), vous pouvez donc l'utiliser pour effectuer également une analyse basée sur des expressions rationnelles.

13
th_in_gs

Correction rapide et sale des fautes de frappe (particulièrement utile pour les commandes longues sur des connexions lentes où l'utilisation de l'historique des commandes et le défilement seraient horribles):

$ cat /proc/cupinfo
cat: /proc/cupinfo: No such file or directory
$ ^cup^cpu

Essayez aussi !:s/old/new qui remplace une fois l'ancien par le nouveau dans la commande précédente.

Si vous souhaitez remplacer plusieurs occurrences, vous pouvez effectuer une substitution globale avec !:gs/old/new.

Vous pouvez utiliser les commandes gs et s avec n'importe quel événement d'historique, par exemple.

!-2:s/old/new

Pour remplacer old par new (une fois) dans l'avant-dernière commande.

13
mihi

Voici deux de mes favoris:

Pour vérifier la syntaxe sans vraiment exécuter le script, utilisez:

bash -n script.sh

Revenez au dernier répertoire (oui je connais pushd et popd, mais c'est plus rapide)

cd -
10
André

Tableaux:

#!/bin/bash

array[0]="a string"
array[1]="a string with spaces and \"quotation\" marks in it"
array[2]="a string with spaces, \"quotation marks\" and (parenthesis) in it"

echo "There are ${#array[*]} elements in the array."
for n in "${array[@]}"; do
    echo "element = >>${n}<<"
done

Plus de détails sur les tableaux (et autres trucs de script bash avancés) peuvent être trouvés dans le Advanced Bash-Scripting Guide .

8
JesperE

Combinaisons de touches magiques des pages bash man:

  • Ctrl + a et Ctrl + e déplacez le curseur au début et à la fin de la ligne actuelle, respectivement.

  • Ctrl + t et Alt + t transposez le caractère et le mot avant le curseur avec celui en cours, puis déplacez le curseur vers l'avant.

  • Alt + u et Alt + l convertir le mot actuel (du curseur à la fin) en majuscules et minuscules.

    Indice: Appuyez sur Alt +  suivi par l'une de ces commandes pour convertir le début du mot actuel.


Bonus man conseils:

  • Lors de la visualisation des pages man, utilisez / pour rechercher du texte dans les pages. Utilisation n pour passer au match suivant ou N pour le match précédent.

  • Accélérez votre recherche d'une commande ou d'une sous-section particulière dans les pages man en profitant de leur mise en forme:

    o Au lieu de taper /history expansion pour trouver cette section, essayez /^history, à l'aide du curseur (^) pour rechercher uniquement les lignes qui commencent par "historique".

    o Essayez /   read, avec quelques espaces de début, pour rechercher cette commande intégrée. Les builtins sont toujours en retrait dans les pages man.

8
Adam Liss

tilisation des opérateurs booléens Infix

Considérez le simple si:

if [ 2 -lt 3 ]
    then echo "Numbers are still good!"
fi

Ça a l'air un peu moche. Pas très moderne. Si vous utilisez des crochets doubles autour de votre expression booléenne, vous pouvez utiliser les opérateurs booléens normaux!

if [[ 2 < 3 ]]
    then echo "Numbers are still good!"
fi
8
Patrick

Exécution d'une commande avant d'afficher l'invite bash

Définissez une commande dans la variable env "Prompt_COMMAND" et elle sera exécutée automatiquement avant chaque invite. Exemple:

[lsc@home]$ export Prompt_COMMAND="date"
Fri Jun  5 15:19:18 BST 2009
[lsc@home]$ ls
file_a  file_b  file_c
Fri Jun  5 15:19:19 BST 2009
[lsc@home]$ ls

Pour les imbéciles d'avril suivants, ajoutez "export Prompt_COMMAND = cd" au .bashrc de quelqu'un, puis asseyez-vous et regardez la confusion se dérouler.

8
Shawn Chin

Vous pouvez ignorer certains fichiers lors de la finalisation de l'onglet en définissant la variable _ FIGNORE.

Par exemple, si vous avez un référentiel de sous-versions et que vous souhaitez naviguer plus facilement,

export FIGNORE=".svn"

vous pouvez maintenant cd sans être bloqué par .svn répertoires.

7
Sionide21

export TMOUT=$((15*60))

Arrêtez bash après 15 minutes d'inactivité, réglé sur 0 pour le désactiver. Je mets généralement ceci dans ~/.bashrc sur mes comptes root. C'est pratique lors de l'administration de vos box et vous pouvez oublier de vous déconnecter avant de vous éloigner du terminal.

7
Mike Nelson

Undo

C-S--Control Shift Minus Annule les actions de frappe.

Kill/Yank

Toute opération de suppression C-w (supprimer le mot précédent), C-k (supprimer jusqu'à la fin de la ligne), C-u (supprimer au début de la ligne) etc ... copie son texte supprimé dans le kill ring, vous pouvez coller le dernier kill avec: C-y et parcourez (et collez) l'anneau des éléments supprimés avec Alt-y

7
ocodo

Expansion du corset

Expansion standard avec {x, y, z}:

$ echo foo{bar,baz,blam}
foobar foobaz fooblam
$ cp program.py{,.bak}  # very useful with cp and mv

Extension de séquence avec {x..y}:

$ echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
$ echo {a..f}{0..3}
a0 a1 a2 a3 b0 b1 b2 b3 c0 c1 c2 c3 d0 d1 d2 d3 e0 e1 e2 e3 f0 f1 f2 f3
5
Tom

Utilisation de l'arithmétique:

if [[ $((2+1)) = $((1+2)) ]]
    then echo "still ok"
fi
5
Vinko Vrsalovic

Un autre petit: Alt+#

commente la ligne actuelle et la déplace dans le tampon d'historique.

Ainsi, lorsque vous assemblez une ligne de commande et que vous devez émettre une commande intermédiaire, par exemple trouver un fichier, vous appuyez simplement sur alt + #, lancez l'autre commande, remontez dans l'historique, décommentez et continuez.

4
neurolabs

Pas vraiment une fonctionnalité mais plutôt une direction: j'ai trouvé de nombreuses "fonctionnalités cachées", des secrets et diverses utilités bash sur commandlinefu.com . Beaucoup des réponses les mieux notées à ces réponses, je les ai apprises sur ce site :)

4
Agos

Accolades au lieu de do et done dans la boucle

For le corps de la boucle est généralement dans do...done (juste un exemple):

for f in *;
do
    ls "$f";
done

Mais nous pouvons utiliser un style C en utilisant des accolades:

for f in *; {
    ls "$f";
}

Je pense que cela semble mieux que do...doneet je préfère celui-ci. Je n'ai encore trouvé cela dans aucune documentation Bash, c'est donc vraiment une fonctionnalité cachée.

4
Fish Monitor

J'ai récemment lu la programmation Csh considérée comme nuisible qui contenait ce joyau étonnant:

Considérez le pipeline:

A | B | C

Vous voulez connaître le statut de C, eh bien, c'est simple: c'est en $ ?, ou $ status en csh. Mais si vous le voulez de A, vous n'avez pas de chance - si vous êtes dans le csh, bien sûr. Dans le Bourne Shell, vous pouvez l'obtenir, bien que cela soit un peu délicat. Voici quelque chose que j'ai dû faire lorsque j'ai exécuté le stderr de dd dans un tube grep -v pour se débarrasser du bruit d'entrée/sortie des enregistrements, mais j'ai dû retourner l'état de sortie du dd, pas celui de grep:

device=/dev/rmt8
dd_noise='^[0-9]+\+[0-9]+ records (in|out)$'
exec 3>&1
status=`((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |
    egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`
exit $status;
4
Greg Hewgill

Tronquer le contenu d'un fichier (fichier de mise à zéro)

> file

Plus précisément, cela est très bon pour tronquer les fichiers journaux, lorsque le fichier est ouvert par un autre processus, qui peut toujours écrire dans le fichier.

4
Thevs

Expressions numériques de style C:

let x="RANDOM%2**8"
echo -n "$x = 0b"
for ((i=8; i>=0; i--)); do
  let n="2**i"
  if (( (x&n) == n )); then echo -n "1"
  else echo -n "0"
  fi
done
echo ""
3
Steve Baker

Ces propriétés sont un autre de mes favoris.

export HISTCONTROL=erasedups
export HISTSIZE=1000

Le premier s'assure que bash n'enregistre pas les commandes plus d'une fois, améliorera vraiment l'utilité de history. L'autre étend la taille de l'historique à 1000 par rapport à la valeur par défaut de 100. J'ai en fait défini cette valeur à 10000 sur mes machines.

3
danieljimenez

Se déplacer facilement entre plusieurs répertoires

Pas une fonctionnalité cachée, mais beaucoup plus flexible que pushd qui nécessite une navigation de type pile.

a() { alias $1=cd\ $PWD; }

cd quelque part et tapez a 1. Plus tard, il suffit de taper 1 retournera dans ce répertoire.

3
David Plumpton

set -o vi afin d'avoir une édition de type vi de l'historique des commandes ainsi que de la commande actuellement tapée.

3

Celui que j'utilise beaucoup est! $ Pour faire référence au dernier mot de la dernière commande:

$ less foobar.txt
...
# I dont want that file any more
$ rm !$
3
camh

J'ai un alias r='fc-s', et je le trouve très utile dans certains cas limités. Pour exécuter la dernière commande, tapez simplement r et appuyez sur Entrée, et c'est tout. Bien sûr, cela n'est pas très utile car la flèche vers le haut fait la même chose. Mais vous pouvez utiliser r pour exécuter la commande précédente avec des substitutions. Disons que votre dernière commande était une longue commande compilant un fichier:

$ gcc -c <file_name>.c <lots of options> -o <file_name>.o

Vous voulez maintenant compiler un autre fichier avec les mêmes options et avoir un .o fichier:

$ r <file_name>=<new_file>

le fera. Vous n'avez pas besoin d'utiliser la flèche vers le haut, de naviguer aux bons endroits, puis de les remplacer manuellement chacun. Cela peut être répété plusieurs fois, vous pouvez donc le faire ensuite:

$ r <new_file>=<other_file>

Bien sûr, pour une telle chose, vous avez des makefiles, mais j'espère avoir montré que l'alias est utile.

Je n'ai pas eu besoin de beaucoup de cet alias, mais il y a eu des moments où je suis content d'avoir cet alias!

2
Alok Singhal

Comme d'autres l'ont mentionné, Ctrl-r est idéal pour revenir en arrière dans l'historique de vos commandes. Mais que se passe-t-il si vous voulez avancer après avoir fait un ou plusieurs pas de trop? C'est là que Ctrl-s est très pratique. Cependant, il est normalement mappé sur XOFF (interruption du flux de données). Comme ce n'est plus trop utile parce que nous n'utilisons pas de terminaux série lents, vous pouvez désactiver ce mappage avec:

stty -ixon

dans ton ~/.bashrc fichier.

Cela fait également Ctrl-q disponible qui est normalement un double de Ctrl-v (entre guillemets qui vous permet d'insérer un caractère de contrôle littéral). j'ai Ctrl-q mappé à menu-complete qui parcourt les complétions lorsqu'il est pressé à plusieurs reprises. J'aime partir Tab réglé sur régulier complet.

Vous pouvez définir Ctrl-q au menu complet en ajoutant cette ligne à votre ~/.inputrc fichier:

"\C-q": menu-complete
2
Dennis Williamson

ici les chaînes (<<<). Le manuel Bash donne cette description:

Le mot est développé et fourni à la commande sur son entrée standard.

Exemple:

$ cat<<<"$(( 10*3+1 )) Nice isn't it?"
31 Nice isn't it?
2
artistoex

Bash a une indirection variable:

$ foo=bar
$ baz=foo
$ echo ${!baz}
bar
2
Dennis Williamson

Noms de fichiers de socket spéciaux:/dev/tcp/Host/PORT et/dev/udp/Host/PORT

Lire à partir d'un serveur de jour (port 13):

$ cat < /dev/tcp/utcnist.colorado.edu/13

55786 11-08-13 03:34:21 50 0 0 172.3 UTC(NIST) *

Cela peut être très utile en conjonction avec tcpserver .

Un exemple plus avancé de http://thesmithfam.org/blog/2006/05/23/bash-socket-programming-with-devtcp-2/ si vous n'avez pas accès à wget ou boucle:

$ exec 3<>/dev/tcp/www.google.com/80 # hook up to file desc 3
$ echo -e "GET / HTTP/1.1\n\n" >&3   # send the HTTP request
$ cat <&3                            # read the HTTP response
1
Tom

Substitution de processus avec <(cmd ...) ou> (cmd ...)

Dans chaque formulaire, le cmd est exécuté avec son entrée ou sa sortie connectée à un FIFO, et le chemin d'accès à celui-ci FIFO est substitué sur la ligne de commande:

$ echo A file to read: <(cat), a file to write to: >(cat)
A file to read: /dev/fd/63, a file to write to: /dev/fd/62

Par exemple, pour comparer deux sites Web sans enregistrer de fichiers intermédiaires:

$ diff <(curl -s http://tldp.org/LDP/abs/html/) <(curl -s http://www.redhat.com/mirrors/LDP/LDP/abs/html/)

Si vous avez une commande qui prend un nom de fichier en entrée, mais n'accepte pas "-" pour signifier stdout, vous pouvez le tromper:

$ do_thingee --log -
error: can't open log file: '-'
$ do_thingee --log >(cat)
do_thingee v0.2
initializing things
processing 4 things
done
1
Tom

tilisation de la commande bash intégrée 'let' pour l'arithmétique de base

A=10
let B="A * 10 + 1" # B=101
let B="B / 8"      # B=12, let does not do floating point
let B="(RANDOM % 6) + 1" # B is now a random number between 1 and 6

Pour effectuer des évaluations en virgule flottante, vous pouvez utiliser la commande "bc" (aucune partie de bash).

FP=`echo "scale=4; 10 / 3" | bc` # FP="3.3333"
1
Shawn Chin

Obtenez plus d'informations sur les combinaisons de touches dans Bash dans http://linuxconfig.net/manual-howto/key-combinations-in-bash.html

0
GEvorg

Substitution de commande intégrée:

nom d'hôte && Dig + short $ (nom d'hôte) && Dig + short -x $ (Dig + short $ (nom d'hôte))

Cette commande est utile pour vérifier RDNS sur votre serveur de messagerie. : P

0
Nathacof

Recherche rapide dans l'historique

Ce qui suit donne une recherche d'historique comme tcsh qui est pratique et plus facile.

Ajoutez les lignes suivantes à ~/.inputrc ou /etc/inputrc.

$ cat ~/.inputrc
"\e[A": history-search-backward
"\e[B": history-search-forward

Vous souhaiterez peut-être utiliser une combinaison de touches moins accidentelle telle que Esc + p. Si tel est le cas, utilisez

"\ep": history-search-backward
"\en": history-search-forward

Ensuite, tapez simplement les premières lettres et appuyez sur la touche Flèche haut. Il montrera la commande la plus récente qui commence par les lettres données.

ex:

tapez grep, UpArrow. Cela montrera quelque chose comme grep -ri myText .

0
Kasun Gajasinghe