2010-04-03 111 views
3

我试图实现我自己版本的'cd'命令,该命令向用户显示可供选择的硬编码目录列表,并且用户必须输入与列表中的条目对应的编号。该程序现在名为my_cd.py,然后应该有效地将用户“cd”到所选目录。如何这应该工作示例:如何从python脚本更改当前目录?

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

/bin 
$ 

目前,我试图用os.chdir('dir')“CD”。但是,这不起作用,可能是因为my_cd.py在其自己的子进程中启动。我想包装调用my_cd.py名为my_cd.sh一个执行的bash脚本:

#! /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 

我如何能得到这个工作任何想法?是否有可能从python脚本中更改交互式shell的当前目录?

回答

1

这是无法完成的。父进程对工作目录的更改不可见。最好你可以让Python脚本打印目录来改变,然后让源脚本切换到那个目录。

+0

这是正确答案!没有办法做到这一点。 – 2010-04-03 14:42:42

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] 

用法:

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

如果您使用单引号,则不必逃避美元符号:'alias mcd ='cd $(/ path/to/my_cd.py)'' – 2010-04-03 16:25:14

6

更改来源bash代码:

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

和Python代码到它的所有cosmetic输出(消息做用户,菜单等)sys.stderr ,并在最后,而不是os.chdir,只是print(到sys.stdout)目录应该改变的路径。

2

为了什么它的价值,因为这个问题也标记为“庆典”,这里是一个简单的bash,唯一的解决办法:

$ 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 

现在,这个脚本必须source'd,不执行:

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

所以,

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

为了解决你的情况,你可以有命令的用户运行的是一个别名,如此请求一个bash脚本,它首先执行目录选择,然后在cd完成后潜入一个python程序。

1

与所说的相反,您可以通过两次更换过程映像来完成此操作。

在bash,替换为您my_cd功能:

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

那么你的Python脚本有完成:

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

记住import os, sys在脚本的开始。

但请注意,这是边界黑客。你的shell会死亡,用python脚本代替它,在同一进程中运行。 python脚本对环境进行了更改,并使用shell替换了它自己,然后再次返回,仍然在同一个进程中。这意味着如果在前一个shell会话中有一些其他本地未保存和未导出的数据或环境,它将不会保留到新的shell会话中。这也意味着rc和profile脚本会再次运行(通常不是问题)。