2010-04-03 5 views
3

J'essaie d'implémenter ma propre version de la commande 'cd' qui présente à l'utilisateur une liste de répertoires codés en dur à choisir, et l'utilisateur doit entrer un nombre correspondant à une entrée dans la liste. Le programme, nommé my_cd.py pour l'instant, devrait alors effectivement 'cd' l'utilisateur dans le répertoire choisi. Exemple de comment cela devrait fonctionner:Comment changer mon répertoire actuel d'un script python?

/some/directory 
$ my_cd.py 
1) ~ 
2) /bin/ 
3) /usr 
Enter menu selection, or q to quit: 2 

/bin 
$ 

Actuellement, je suis en train de « cd » en utilisant os.chdir('dir'). Cependant, cela ne fonctionne pas, probablement parce que my_cd.py est lancé dans son propre processus fils. J'ai essayé envelopper l'appel à my_cd.py dans un script bash nommé source my_cd.sh:

#! /bin/bash 
function my_cd() { 
    /path/to/my_cd.py 
} 

/some/directory 
$ . my_cd.sh 
$ my_cd 
... shows list of dirs, but doesn't 'cd' in the interactive shell 

Toutes les idées sur la façon dont je peux obtenir ce travail? Est-il possible de changer le répertoire courant de mon shell interactif à partir d'un script python?

Répondre

1

Cela ne peut pas être fait. Les modifications apportées au répertoire de travail ne sont pas visibles pour les processus parents. Au mieux, vous pouvez faire en sorte que le script Python imprime le répertoire à modifier, puis que le script source soit changé en ce répertoire.

+0

Ceci est la bonne réponse! Il n'y a aucun moyen de le faire. –

3

my_cd.py:

#!/usr/bin/env python 
import sys 

dirs = ['/usr/bin', '/bin', '~'] 
for n, dir in enumerate(dirs): 
    sys.stderr.write('%d) %s\n' % (n+1, dir)) 
sys.stderr.write('Choice: ') 
n = int(raw_input()) 
print dirs[n-1] 

Utilisation:

nosklo:/tmp$ alias mcd="cd \$(/path/to/my_cd.py)" 
nosklo:/tmp$ mcd 
1) /usr/bin 
2) /bin 
3) ~ 
Choice: 1 
nosklo:/usr/bin$ 
+0

Vous n'avez pas besoin d'échapper le signe dollar si vous utilisez des guillemets simples: 'alias mcd = 'cd $ (/ chemin/vers/my_cd.py)'' –

6

Changer votre source Code bash à:

#! /bin/bash 
function my_cd() { 
    cd `/path/to/my_cd.py` 
} 

et votre code Python pour faire toutes ses cosmetic sortie (messages à les utilisateurs, les menus, etc.) sur sys.stderr , et, à la fin, au lieu de os.chdir, juste printsys.stdout) le chemin vers lequel le répertoire doit être modifié.

2

Pour ce que ça vaut, puisque cette question est également marqué "bash", voici est un simple bash seule solution:

$ cat select_cd 
#!/bin/bash 

PS3="Number: " 

dir_choices="/home/klittle /local_home/oracle" 

select CHOICE in $dir_choices; do 
    break 
done 

[[ "$CHOICE" != "" ]] && eval 'cd '$CHOICE 

Maintenant, ce script doit être source'd, non exécuté:

$ pwd 
/home/klittle/bin 
$ source select_cd 
1) /home/klittle 
2) /local_home/oracle 
Number: 2 
$ pwd 
/local_home/oracle 

Ainsi,

$ alias mycd='source /home/klittle/bin/select_cd' 
$ mycd 
1) /home/klittle 
2) /local_home/oracle 
Number: 

Pour résoudre votre cas, vous pourriez avoir la commande que l'utilisateur exécute être un alias afin urces un script bash, qui fait d'abord la sélection de dir, puis plonge dans un programme python après que le cd ait été fait.

1

Contrairement à ce qui a été dit, vous pouvez le faire en remplaçant l'image de process, deux fois.

En bash, remplacez votre fonction my_cd avec:

function my_cd() { 
    exec /path/to/my_cd.py "$BASH" "$0" 
} 

Ensuite, votre script python doit se terminer par:

os.execl(sys.argv[1], sys.argv[2]) 

Souvenez-vous de import os, sys au début du script.

Mais notez qu'il s'agit d'un hack borderline. Votre shell meurt, se remplaçant par le script python, exécutant dans le même processus. Le script python apporte des modifications à l'environnement et se remplace par le shell, de retour, toujours dans le même processus. Cela signifie que si vous avez d'autres données ou environnements locaux non sauvegardés et non exportés dans la session shell précédente, ils ne persisteront pas dans la nouvelle session. Cela signifie également que les scripts rc et profile seront exécutés à nouveau (ce qui ne pose généralement pas de problème).

Questions connexes