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 :

Expansion tardive du tilde


Sujet :

Shell et commandes GNU

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 102
    Par défaut Expansion tardive du tilde
    J'ai cherché sur internet mais n'ai pas trouvé de réponse complètement satisfaisante.

    Supposons qu'une variable contienne le nom d'un répertoire ou d'un fichier, commençant par ~, par exemple, parce que c'est plus sympa à afficher.
    Y a-t-il moyen de demander au shell l'expansion a posteriori du tilde?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    dir="~/TMP"
    echo "Votre dir est '$DIR'"
    => Votre dir est '~/TMP'   # ok. c'est ce que je veux
     
    echo "Votre dir '$DIR' contient:"
    => Votre dir '~/TMP' contient:   # ok. c'est toujours ce que je veux
     
    ls $DIR
    => ls: ~/TMP: No such file or directory # Pourtant ~/TMP existe... ou, au moins, $HOME/TMP
     
    cd $DIR
    => -bash: cd: ~/TMP: No such file or directory
     
    for f in $somedir/* ; do echo $f; done
    => ~jack/TMP/*   # Bof... je préfèrerais la liste des fichiers de $HOME/TMP
    J'ai trouvé des solutions partielles, comme:
    mais elle utilise eval (qui est dangereux... bon, a priori, je sais ce que j'ai mis dans "$dir"...)

    Et elle ne marche pas bien s'il y a des espaces:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    dir="~/dir with spaces"
    eval cd "$dir"
    => -bash: cd: /Users/jack/dir: No such file or directory
    Autre proposition, remplacer "~" par "$HOME", mais ça ne marche pas pour un autre home:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    dir="~jack/TMP";
    cd ${dir/#\~/$HOME}
    => -bash: cd: /Users/jackjack/TMP: No such file or directory
     
    cd $(echo $dir | sed "s#^~#$HOME#")
    => -bash: cd: /Users/jackjack/TMP: No such file or directory
    J'ai bien réussi à bidouiller la première avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    dir="~jack/dir with spaces"
    eval "ls -ld $(echo "$dir" | sed -e 's|/\(.*\)|/"\1"|')"
    drwxrwxr-x  2 jack  staff  68 17 déc  2014 /Users/jack/dir with spaces/
    mais j'ai encore un appel à eval...

    Voyez-vous des bugs dans cette dernière solution?
    Connaissez-vous un moyen de faire sans eval?

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 134
    Par défaut
    Et que donne ceci ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    mydir='~/TMP'
    exp=$(cd "$mydir"; pwd)
    echo "'$mydir' est '$exp'"
    Désolé, je n'ai pas de machine *nix sous la main pour tester
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Membre chevronné
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 563
    Par défaut
    Salut, il ne faut pas encadrer ~ de " sinon il n'est pas interpreté.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    cd "~"
    bash: cd: ~: Aucun fichier ou dossier de ce type
    cd ~
    => ok
    Sinon il faut utiliser ${HOME}.

    "${HOME}/Downloads" = ~/Downloads
    "${HOME}/Downloads 2" = ~/Downloads\ 2
    "${HOME}/Downloads 2" = ~"/Downloads 2"

    Ce n'est pas une bonne idée d'utiliser eval pour se déplacer :p

  4. #4
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 349
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 349
    Par défaut
    Bonjour,

    Si perl ne te rebute pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ DIR="~/Bibliothèque calibre"
    $ ls "$(perl -e 'print glob("\"$ARGV[0]\""),qq<\n>' "$DIR")"/*
    /home/disedorgue/Bibliothèque calibre/metadata.db  /home/disedorgue/Bibliothèque calibre/metadata_db_prefs_backup.json
     
    /home/disedorgue/Bibliothèque calibre/John Schember:
    Guide de demarrage rapide (1)

  5. #5
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 349
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 349
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    Bonjour,

    Si perl ne te rebute pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ DIR="~/Bibliothèque calibre"
    $ ls "$(perl -e 'print glob("\"$ARGV[0]\""),qq<\n>' "$DIR")"/*
    /home/disedorgue/Bibliothèque calibre/metadata.db  /home/disedorgue/Bibliothèque calibre/metadata_db_prefs_backup.json
     
    /home/disedorgue/Bibliothèque calibre/John Schember:
    Guide de demarrage rapide (1)
    Une version plus courte et plus propre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ls "$(perl -e 'print <"$ARGV[0]">,qq<\n>' "$DIR")"/*

  6. #6
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    si c'est pour du perso, que les données entrantes sont contrôlées, eval est probablement la meilleure solution à envisager
    sinon, je vois pas d'autre moyen que de réimplémenter l'expansion du tilde, ça doit se faire assez facilement et les homedirs sont dispo dans /etc/passwd en lecture pour tout le système par défaut

  7. #7
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 102
    Par défaut
    Citation Envoyé par hizoka Voir le message
    Salut, il ne faut pas encadrer ~ de " sinon il n'est pas interpreté.
    Oui, je sais (voir mon 1er message)!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    cd "~"
    bash: cd: ~: Aucun fichier ou dossier de ce type
    cd ~
    => ok
    Oui, je sais (voir mon 1er message)!

    Sinon il faut utiliser ${HOME}.

    "${HOME}/Downloads" = ~/Downloads
    "${HOME}/Downloads 2" = ~/Downloads\ 2
    "${HOME}/Downloads 2" = ~"/Downloads 2"
    Oui, je sais (voir mon 1er message)!
    Mais je voudrais stocker une liste de répertoires à présenter à l'utilisateur sous une forme comme "~jack/dir with spaces" qui est plus agréable à regarder que la forme expansée, comme "/Users/jack/dir\ with\ spaces".
    Et ensuite, je veux retrouver la forme expansée à partir de la forme non expansée.

    Ce n'est pas une bonne idée d'utiliser eval pour se déplacer :p
    Oui, je sais (voir mon 1er message)!

  8. #8
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    for fnu, c'est pas dingue mais ça doit faire le job à peu près correctement, à tester :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function expandtilde {
       tildeprefix=$(grep -Po "^~.*?(?=/|$)" <<< "$1")
       tildeprefixlen=${#tildeprefix}
       if [ -n $tildeprefix ]; then
          if [ $tildeprefixlen != 1 ]; then
             homedir=$(awk -F: -vUSERNAME=${tildeprefix:1} '$1 == USERNAME {print $6}' /etc/passwd)
          else
             homedir=$HOME
          fi
       fi
       echo "${homedir}${1:$tildeprefixlen}"
    }
     
    dir="~testuser/testdir"
    echo "dir = $dir"
    expandtilde "$dir"
    (sinon +1 pour la solution Perl )

  9. #9
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 102
    Par défaut
    Citation Envoyé par BufferBob Voir le message
    for fnu, c'est pas dingue mais ça doit faire le job à peu près correctement, à tester :
    Merci!
    Bon, ça fait pas les "~+N" et les "~-N", mais c'est pas grave...

    ça marche pas sous macos qui utilise Open Directory à la place de /etc/passwd...
    Oui, je sais, j'aurais dû poster dans "Shell et commandes POSIX"...


    (sinon +1 pour la solution Perl )
    et disedorgue pour la solution Perl

    Je passe en !

  10. #10
    Membre chevronné
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 563
    Par défaut
    j'avais pas pigé en effet, désolé...
    J'ai lu trop vite sûrement.

    Mais bon maintenant que j'ai répondu à côté, je suis plus à une connerie prêt...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    dir="~/Download/Nouveau dossier/"
    cd "$(sed "s@~@${HOME}@" <<< "${dir}")"
    # =>/home/hizoka/Download/Nouveau dossier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    dir="~hizoka/Download/Nouveau dossier/"
    cd "$(sed "s@~${USER}@${HOME}@" <<< "${dir}")"
    # =>/home/hizoka/Download/Nouveau dossier
    PS :
    une liste de répertoires à présenter à l'utilisateur sous une forme comme "~jack/dir with spaces" qui est plus agréable à regarder
    Pas d'accord mais bon XD => ~jack beurk je trouve... mais ça ne rentre pas en ligne de compte...

  11. #11
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 349
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 349
    Par défaut
    Citation Envoyé par BufferBob Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function expandtilde {
       tildeprefix=$(grep -Po "^~.*?(?=/|$)" <<< "$1")
       tildeprefixlen=${#tildeprefix}
       if [ -n $tildeprefix ]; then
          if [ $tildeprefixlen != 1 ]; then
             homedir=$(awk -F: -vUSERNAME=${tildeprefix:1} '$1 == USERNAME {print $6}' /etc/passwd)
          else
             homedir=$HOME
          fi
       fi
       echo "${homedir}${1:$tildeprefixlen}"
    }
    Si sous MacOS, tu as aussi la commande lslogins (mais pas sure, puisqu'elle est typique linux et inspirée de la commande logins de FreeBSD)...:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    expandtilde () 
    { 
        tildeprefix=$(grep -Po "^~.*?(?=/|$)" <<< "$1");
        tildeprefixlen=${#tildeprefix};
        if [ -n $tildeprefix ]; then
            if [ $tildeprefixlen != 1 ]; then
                homedir=$( lslogins --noheadings -o HOMEDIR -l ${tildeprefix:1} );
            else
                homedir=$HOME;
            fi;
        fi;
        echo "${homedir}${1:$tildeprefixlen}"
    }

  12. #12
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 102
    Par défaut
    Citation Envoyé par al1_24 Voir le message
    Et que donne ceci ?
    Ça donne exactement ce que j'ai indiqué à la ligne 12:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    mydir='~/TMP'
    exp=$(cd "$mydir"; pwd)
    -bash: cd: ~/TMP: No such file or directory
    echo "'$mydir' est '$exp'"
    '~/TMP' est '/Users/jack'
    car le '~' n'est pas expansé...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Apache Debian tild
    Par ange91160 dans le forum Apache
    Réponses: 2
    Dernier message: 29/12/2006, 21h20
  2. Inscription universitaire tardive
    Par Ryadus dans le forum Etudes
    Réponses: 1
    Dernier message: 20/11/2006, 21h37
  3. Tild ' dans ACCESS
    Par TOPGUN89 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 31/08/2006, 09h32
  4. Problème : touche "tilde" ne fonctionne plus
    Par nicolas.charlot dans le forum Windows XP
    Réponses: 4
    Dernier message: 04/06/2006, 19h33
  5. [JTreeTable] expansion/collapse d'un noeud
    Par Hammer dans le forum Composants
    Réponses: 4
    Dernier message: 30/04/2003, 22h58

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