IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Trucs et astuces


Sujet :

Shell et commandes GNU

  1. #1
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut Trucs et astuces
    Bonjour,

    Les langages de script ne sont pas toujours évidents à programmer, il y a souvent des trucs et astuces à connaître. En lisant ce forum et en cherchant à résoudre certains des problèmes, j'en ai découvert plusieurs. Il s'agit parfois de commandes peu usitées, d'options très intéressantes, ou de petits bouts de code bien sympa. Je vous propose de partager ces connaissances pour un enrichissement mutuel .

    Essayons d'être clair en:
    * mettant un intitulé,
    * décrivant rapidement le problème,
    * donnant la (une) solution (et type de shell si nécessaire),
    * relisant le post pour corriger les fautes.

    Je vous remercie par avance pour votre participation... Il peut s'agir de choses très basiques, je vais d'ailleurs commencer par ça .

  2. #2
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut Option LS
    Je commence donc avec un truc des plus simples:

    Problème:
    Dans un script, j'ai besoin de lister tous les fichiers, même ceux cachés (.*). La commande ls -a me donne bien ce que je veux, mais il y a les répertoires . (répertoire courant) et .. (répertoire parent) qui sont toujours là et me gênent.

    Solution:
    Plutôt que de nettoyer la liste obtenue par ls -a, la commande ls -A donne directement la bonne liste.

    Basique, n'est-ce pas? Alors "à vous Cognac-Jay, à vous les studios!"

  3. #3
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut Alias et non-alias
    Problème:
    Les alias sont très intéressants pour accélérer le "tapage" des commandes. Style ll pour ls -l. Il suffit de taper alias pour voir ce qui est disponible. Pour le root, j'obtiens (Fedora 8):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    alias cp='cp -i'
    alias l.='ls -d .* --color=auto'
    alias ll='ls -l --color=auto'
    alias ls='ls --color=auto'
    alias mv='mv -i'
    alias rm='rm -i'
    alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
    Cependant, dans un script, je peux vouloir supprimer un fichier sans avoir à confirmer manuellement que "oui, je veux effectivement supprimer ce p!@#$n de fichier!" Comment ne pas utiliser l'alias rm='rm -i' dans mon script?

    Deux solutions:
    * En mettant le chemin absolu de la commande /bin/rm mon_fichier.
    * En échappant la commande \rm mon_fichier.

  4. #4
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut CUT vs AWK
    Problème:
    La commande cut est simple, mais sans doute trop: le délimiteur (option -d ' ', par exemple) est pris de manière très stricte. Sur le fichier mon_fichier contenant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    champ_1 champ_2  champ_3
    la commande cut -d ' ' -f 3 mon_fichier ne sort rien, alors que je m'attendais à avoir champ_3. C'est parce qu'il y a 2 espaces entre champ_2 et champ_3, donc -f 3 est vide (entre les deux espaces) et -f 4 vaut champ_3.

    Solution:
    La commande awk fonctionne différemment: qu'il y ait un ou plusieurs séparateurs consécutifs, cette commande considère qu'il n'y en a qu'un seul. Donc la commande awk '{print $3}' donne bien champ_3. L'option -d ' ' de cut équivaut à l'option -F ' ' de awk, mais par défaut c'est l'espace, la tabulation ou le retour chariot. Oui, il peut y avoir plusieurs séparateurs ou même pas du tout. Lisez man awk et vous aurez l'air d'un pro...

  5. #5
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut ECHO et guillemets, avec ou sans?
    Problème:
    Lorsqu'il faut enchainer les pipes (pas de jeux de mots siouplé), le formattage de sortie d'une commande doit correspondre à la commande suivante. La commande echo prend beaucoup de libertés avec les retours-chariot. Par exemple: echo $(ls) donne une suite de fichiers séparés par un espace. Il y a bien un '\n' entre chaque nom dans la variable a, mais il est transformé en ' ' par echo! En effet, chaque nom est une entrée séparée et echo ajoute son séparateur qui est l'espace.

    Solution:
    Les guillemets! La commande echo "$(ls)" laisse la chaîne de caractères telle quelle puisqu'il n'y a plus qu'une seule entrée.

  6. #6
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut Trier sur les champs (SORT)
    Problème:
    Comme j'en ai déjà parlé sur un autre fil, certains fichiers à trier sont constitués de plusieurs champs, le fichier /etc/passwd par exemple. La simple commande sort /etc/passwd donne parfois des surprises. Essayez, vous verrez.

    Solution:
    Demandez (gentiment) à la commande sort de trier suivant le(s) champ(s) que vous désirez (les champs doivent être consécutifs): sort -t ':' -k 1,1 /etc/passwd. Cela veut dire: trier le fichier comportant plusieurs champs séparés par ':' depuis le champ 1 jusqu'au champ 1. Cette fois-ci, le séparateur n'est pas testé comme simple caractère et le tri devient correct...

  7. #7
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut JOIN, c'est fumeux
    Problème:
    J'ai deux gros fichiers qui ont divers champs séparés par ':'. Le premier champ de chacun des deux fichiers est important, c'est l'identificateur, il est toujours existant et il n'y a pas de doublon (c'est une clé). Je voudrais être sûr que tous les identificateurs de fichier_1 (plus de 1000 lignes) sont bien dans fichier_2 (plus de 10000 lignes!), et sinon il faut me montrer les lignes qui manquent... Ho la la! Des boucles, des fichiers à lire de multiples fois... Vite, un Aspro.

    Solution:
    La commande join est mon amie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    join -t ':' -v 1 fichier_1 fichier_2
    L'option -v de join n'est pas verbose mais plutôt inVert, comme dans grep: Les lignes qui ne sont pas dans $1 (fichier_1) et dans $2 (fichier_2) seront affichées. Malheureusement, ce n'est pas si simple: pour que ça marche, il faut que les deux fichiers soient triés (clés triées). D'où un petit tour au post précédent sur sort. Finalement, les trois lignes suivantes règlent élégamment le problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    sort -t ':' -k 1,1 fichier_1 > fichier_1.sorted
    sort -t ':' -k 1,1 fichier_2 > fichier_2.sorted
    join -t ':' -v 1 fichier_1.sorted fichier_2.sorted
    Et voili voilou, il manquait bien une p!@#$n de ligne dans fichier_2, j'ai vérifié avec un grep. Tiens, à propos de grep...

  8. #8
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut Prompt Bash
    Problème:
    Lorsque je liste des gros fichiers (cat ou more), je reviens en arrière avec l'ascenseur, mais j'ai du mal à voir où est le début. Je dépasse et parfois je me retrouve dans la liste précédente. Ha, si le prompt était plus visible, et tant qu'à faire ma lettre au Père-Noël, je voudrais aussi un prompt bien différent pour root. Signé jmelyn qui a été bien sage cette année.

    Solution:
    Réponse du Père-Noël dans mon soulier:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    # Pour root, à mettre à la fin de son fichier /root/.bashrc:
    PS1="\[\033[41;1;37m\][\u@\h]\[\033[m\] \w # \[\033[0;37;00m\]"
     
    # Pour toi, à mettre à la fin de ton fichier $HOME/.bashrc:
    PS1="\[\033[40;1;37m\][\u@\h]\[\033[m\] \w $ \[\033[0;37;00m\]"
    On obtient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    [root@grosse_bête] ~ #  
    [jmelyn@grosse_bête] ~ $
    En fait non, je n'arrive pas à montrer le résultat ici, il y a de l'inversé. Essayez donc! Au fait, faudrait que je remercie le Vieux...

  9. #9
    Membre éclairé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Août 2007
    Messages
    509
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Août 2007
    Messages : 509
    Par défaut
    Citation Envoyé par jmelyn Voir le message
    Cependant, dans un script, je peux vouloir supprimer un fichier sans avoir à confirmer manuellement que "oui, je veux effectivement supprimer ce p!@#$n de fichier!" Comment ne pas utiliser l'alias rm='rm -i' dans mon script?

    Deux solutions:
    * En mettant le chemin absolu de la commande /bin/rm mon_fichier.
    * En échappant la commande \rm mon_fichier.
    Moi je conseille rm -f mon_fichier pour forcer la suppression du fichier sans confirmation !!

  10. #10
    Membre émérite
    Avatar de D[r]eadLock
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    504
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 504
    Par défaut
    Citation Envoyé par publicStaticVoidMain Voir le message
    Moi je conseille rm -f mon_fichier pour forcer la suppression du fichier sans confirmation !!
    Non, si y'a -i, -fi demande quand-même la confirmation. Mais la question est biaisée, dans un script les alias ne sont utilisés donc le /bin/rm et \rm ne servent pas dans un script.

  11. #11
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    @ publicStaticVoidMain:
    Tu as raison! C'est pas bien de se fier simplement à ses souvenirs sans vérifier...

    Le problème que j'avais eu était avec la commande cp: en étant root, cp titi toto, alors que toto existe déjà, donne dans l'interactif. Et cp -f est fait pour autre chose: lorsque le fichier de destination n'est pas accessible en écriture, alors il est détruit avant la copie.

    Donc pour reprendre un exemple qui marche, en étant root:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    echo toto > toto
    echo titi > titi
    cp titi toto
    cp: overwrite `toto'? n
    \cp titi toto
    cat toto
    titi
    Dans ce cas, l'"anti-alias" est intéressant. Merci pour la correction, privateVolatileIntMain

  12. #12
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    @ D[r]eadLock:
    J'écris de petites histoires qui ne me sont pas arrivées, mais qui permettent de mieux comprendre l'intérêt. Pour la commande rm, c'était pas le top, d'autant que je n'avais encore pas remarqué que les alias ne sont pas actifs dans les scripts. Merci donc.

  13. #13
    Membre éclairé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Août 2007
    Messages
    509
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Août 2007
    Messages : 509
    Par défaut
    Citation Envoyé par D[r]eadLock Voir le message
    Non, si y'a -i, -fi demande quand-même la confirmation. Mais la question est biaisée, dans un script les alias ne sont utilisés donc le /bin/rm et \rm ne servent pas dans un script.
    Ca dépend, le man de rm explique si les 2 options -f et -i sont fournies, la dernière sur la ligne de commande a l'avantage.

    donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    2401939@ari-31-305-01:/users/nfs/Etu9/2401939$ touch fic
    2401939@ari-31-305-01:/users/nfs/Etu9/2401939$ rm -fi fic 
    rm: détruire fichier régulier vide `fic'? o
    détruit `fic'
    2401939@ari-31-305-01:/users/nfs/Etu9/2401939$ touch fic
    2401939@ari-31-305-01:/users/nfs/Etu9/2401939$ rm -if fic 
    détruit `fic'
    2401939@ari-31-305-01:/users/nfs/Etu9/2401939$

  14. #14
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut Calculs de dates
    Problème (honteusement pompé dans un fil à côté):
    J'ai besoin de connaître la date d'hier, de demain, de dans deux ans, et en toute lettes, chiffres, et caetera. Autre problème: Combien d'heures, de jours, de semaines entre deux dates? Vite, ma calculatrice, le calandrier grégorien, julien et tutti quanti!

    Solution:
    Du calme, je suis sûr de ne pas être le premier à me confronter à cette situation, des solutions simples doivent bien exister... Et bin ouais! Ouf! Le truc se décompose en plusieurs étapes:
    1) Passer la (les) date(s) du format humain au format ordi, c'est-à-dire en nombre de secondes depuis le 1er janvier 1970. Mais ça marche quand même pour les dates d'avant...
    2) Faire les calculs avec ce(s) nombre(s) en secondes.
    3) Repasser au format humain si nécessaire.
    Donc je ne vais pas réinventer le fil à couper l'eau chaude, je risque de me tromper et mes calculs seront certainement plus longs à exécuter.

    Exemple 1: L'effondrement du mur de Berlin, c'était quel jour?
    D'abord, petit tour sur Wikipépia me donne le 09 novembre 1989.
    Puis, le man de date -d m'indique comment passer la date en nombre de secondes.
    Ensuite le man de awk au châpitre Time functions me propose strftime() qui me va bien.
    Enfin, le man de strftime, fonction C, me fournit le bon argument: %A.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    date -d 1989-11-09 +%s | awk '{print strftime("%A", $0)}'
    Thursday
    Exemple 2: Il y a combien de jours que la mise à jour a eu lieu?
    J'ai un fichier qui me donne la date: "Thu Oct 2 12:00:01 CEST 2008"
    Le programme bc me donne le nombre de secondes en une journée (24 * 3600 = 86400).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    echo $(( ($(date +%s) - $(date -d "Thu Oct  2 12:00:01 CEST 2008" +%s)) / 86400 ))
    6
    Attention, le résultat est tronqué, ça peut être 6,00 ou 6,99.

  15. #15
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut Dans la pénombre du tunnel (SSH)
    Problème:
    Il y a plein de services au boulot que j'aimerais utiliser à la maison, comme le mail, mais sans avoir à passer par un client web (que je déteste). Malheureusement Thunderbird n'arrive pas à s'y connecter. Normal, m'a-t-on répondu, de l'extérieur ça marche que sous Windows! .

    Solution:
    Pas de panique, ssh est là. Prenons le cas du serveur SMTP: je dis à Thunderbird qu'il est assis directement dessus (localhost), à un port plus grand que 1024, pour ne pas être root chaque fois que je veux envoyer un mail.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Server Name: localhost
    Port: 1025
    Cela est à faire une fois pour toute. Ensuite j'ouvre une connexion ssh avec l'unique ordinateur visible de la boîte, ordi_boite, avec les options magiques à chaque session où je veux envoyer un e-mail:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ssh -L 1025:smtp_server:25 jmelyn@ordi_boite
    Explications:
    Le client ssh à la maison écoute sur le port 1025 (vers lequel parle Thunderbird lorsque j'envoie un e-mail), transfert les données vers ordi_boite puis les renvoie vers le serveur smtp_serveur (celui qui est caché dans la boîte), port 25, celui de smtp. Maintenant j'envoie tous les mails que je veux depuis Thunderbird à la maison, et j'ai pas Windows!

  16. #16
    Membre émérite
    Avatar de D[r]eadLock
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    504
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 504
    Par défaut
    Méa culpa pour le -f. C'était bien sur le cp (et non le rm) où le -f ne "marche" pas comme on pourrait s'y attendre (comme dit ci-dessus) et où la soluce du \cp marche bien.

    Sinon pour l'exemple 1 de date, on peut tout faire avec date (du moins dans ses versions plus récentes avec date -d @timestamp):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    > date -d @`date -d 1989-11-09 +%s` +%A
    Thursday
    Sinon, tout ça n'est pas pour remettre ne question les astuces au contraire mais plus pour développer (pour ceux que ça intéresse...)

    Enfin ce thread pourrait pourrais peut-être mis en FAQ/Important (voire même en intégrant les threads résolus reformatés)... un rédacterur/modo motivé ?

  17. #17
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Bonjour,

    D'abord, bravo D(r)eadLock pour les fonctions cachées de date: le man ne dit rien sur l'argument @, mais le info si. J'ai un peu de mal à me ballader dans ce dernier système, mais je devrais vraiment regarder.

    Et puis c'est vrai, quelque chose de différent qu'un fil-forum serait bien pour synthétiser les "découvertes" que nous faisons grâce aux uns et aux autres. Il est normal et même bon que les solutions s'affinent et tout lire un fil pour avoir la solution finale à un problème peut amener des oublis. Reformatter, corriger et mettre à jour une sorte de FAQ serait, selon moi, un vrai bon point: Les mêmes questions finissent par revenir. Au fil du temps, cette base de connaissance serait une référence pour les utilisateurs.

  18. #18
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut Répertoire de travail
    Allez, vendredi aprèm: il est temps de continuer la liste.

    Problème:
    La plupart de mes scripts prennent un ou des fichiers en entrée, travaillent les données de multiples façons et donnent un ou plusieurs fichiers en sortie. Les traitements peuvent être long et complexes et nécessitent souvent plusieurs traitements à la suite. J'utilise donc des fichiers temporaires. Le problème est le nommage de ces fichiers, ainsi que leur nettoyage. Où les mettre? Dans le répertoire du (des) fichiers d'entrée, de sortie?

    Solution:
    Comme les autres personnes (admins) n'apprécient pas avoir des fichiers temporaires noyant les fichiers importants, j'évite absolument de mélanger les fichiers: il suffit qu'un script soit tué pour avoir des fichiers temporaires partout. Comme la petite plaquette aux toilettes l'indique: "Vous êtes prié de laisser l'endroit aussi propre que vous l'avez trouvé en entrant", faut bien ranger après. Donc /tmp est un bon candidat pour les fichiers temporaires. Néanmoins, si deux admins lancent le même script en même temps, il risque d'y avoir mélange de pinceaux. Voici finalement ce que j'utilise le plus souvent possible.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tmpDir=$(mktemp -d /tmp/$(basename $0).XXX)
    Donc je mets tous mes fichiers temporaires dans /tmp/<nom_script>.XXX. Le nom du script est évidemment utile pour comprendre d'où vient ce répertoire, les XXX sont trois caractères aléatoires pour éviter les conflits entre plusieurs exécutions simultanées. Le possesseur du répertoire est celui qui a lancé le script.

    À l'intérieur de ce répertoire, je crée des noms de fichier du genre: tmp.initial, tmp.sorted, tmp.before_cleanup. Ainsi, il est facile de débuguer en lisant chaque étape du programme.

    Un petit détail encore:
    SIl faut penser à nettoyer (rm -rf $tmpDir) à chaque sortie possible du script (commande exit). Pour ma part, au lieu de faire un exit, je crée la fonction end qui nettoie et fait tous les traitements nécessaires de fin de script. Facile alors de commenter le rm -rf $tmpDir pour conserver les fichiers afin de débuguer!

  19. #19
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut Single-quote or double-quote? That is the question!
    Texte repris d'un fil à propos de sed: Quelles différences y a-t-il entre les chaînes délimitées par ' (single-quote) et celles délimitées par " (double-quote)?
    • ": à l'intérieur de double-quotes, Bash considère que c'est une chaîne de caractères à ne pas interpréter, sauf pour 4 caractères spéciaux:
      • $: évaluation de 3 types d'expression:
        • contenu de variable: echo "$SHELL" donne /bin/bash
        • retour de commande: echo "heure: $(date +%H:%M)" donne heure: 13:00
        • résultat de calcul arithmétique: echo "1 + 1 = $((1 + 1))" donne 1 + 1 = 2
      • `: back-quote, echo "heure: `date +%H:%M`" est synonyme de echo "heure: $(date +%H:%M)"
      • \: utilisé pour échapper (c'est-à-dire supprimer le sens spécial) les 5 caractères spéciaux suivants:
        • $: echo "caractère dollar: \$" donne caractère dollar: $
        • `: echo "caractère back-quote: \`" donne caractère back-quote: `
        • ": echo "caractère double-quote: \"" donne caractère double-quote: "
        • \: echo "caractère back-slash: \\" donne caractère back-slash: \
        • retour-chariot: si un \ est en fin de ligne dans une chaîne entre " et ", alors la chaîne continue sur la ligne suivante sans ce retour-chariot. echo "ligne1, \
          encore ligne 1 :-)"
          donne ligne 1, encore ligne 1 :-)
      • !: utilisé pour l'historique des commandes. Entre double-quotes, il est impossible d'échapper ce caractère, ce sera toujours l'historique. Par exemple chez moi, echo "!ssh" donne ssh -L 1025:smtp:25 -L 1636:ldap:636 serveur.du.boulot: c'est ma dernière commande commençant par ssh.
    • ': à l'intérieur de single-quotes, Bash considère que c'est une chaîne de caractères à ne pas interpréter du tout. L'interpréteur recherche simplement le second single-quote qui termine la chaîne, sans plus. Impossible donc de mettre un single-quote à l'intérieur d'une chaîne délimitée par single-quotes!

  20. #20
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut Boucle for comme en C, c'est possible?
    Problème:
    En langage de script en général, et en Bash en particulier, il est possible de passer en revue la liste des fichiers d'un répertoire par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for fichier in $(echo *.c)
    do
        head -20 $fichier
    done
    Mais lorsqu'on veut faire une action 10 fois par exemple, ça ne marche pas!

    Solutions:
    Une première possibilité est d'utiliser la commande seq:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for i in $(seq 10)
    do
        echo "i: $i"
    done
    Et la seconde possibilité est d'utiliser la syntaxe arithmétique de Bash:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for ((i = 1; i <= 10; i++))
    do
        echo "i: $i"
    done
    Bon, la première solution est certainement plus portable vers les autres shells...

Discussions similaires

  1. [Truc et Astuce] - Raccourci universel
    Par e040098k dans le forum Contribuez
    Réponses: 0
    Dernier message: 13/08/2007, 20h11
  2. Recherche trucs et astuces en C
    Par gwendal86 dans le forum Réseau
    Réponses: 20
    Dernier message: 22/10/2006, 12h37
  3. trucs et astuces XML
    Par grishka dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 09/09/2004, 14h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo