如何从python脚本更改当前目录?

如何从python脚本更改当前目录?,python,bash,shell,directory,cd,Python,Bash,Shell,Directory,Cd,我正在尝试实现我自己版本的“cd”命令,该命令向用户提供一个硬编码目录列表供选择,用户必须输入与列表中某个条目对应的数字。现在名为my_cd.py的程序应该有效地将用户“cd”到所选目录。这应该如何工作的示例: /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”命令,该命令向用户提供一个硬编码目录列表供选择,用户必须输入与列表中某个条目对应的数字。现在名为
my_cd.py
的程序应该有效地将用户“cd”到所选目录。这应该如何工作的示例:

/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的当前目录?

这无法完成。对工作目录的更改对父进程不可见。您最多可以让Python脚本打印要更改的目录,然后让源脚本实际更改到该目录。

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$ 

将源代码bash更改为:

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

您的Python代码在
sys.stderr
上执行其所有的
外观输出(向用户、菜单等发送的消息),最后,不再是
os.chdir
,只需
打印
(到
sys.stdout
)目录应该更改的路径即可,因为这个问题也被标记为“bash”,所以这里有一个简单的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
现在,此脚本必须是源代码,而不是执行:

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


为了解决您的问题,您可以让用户运行的命令是一个别名,它可以生成一个bash脚本,该脚本首先进行dir选择,然后在cd完成后潜入python程序。

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

在bash中,将my_cd函数替换为:

function my_cd() {
    exec /path/to/my_cd.py "$BASH" "$0"
}
然后,您的python脚本必须完成以下操作:

os.execl(sys.argv[1], sys.argv[2])
请记住在脚本开头导入操作系统、系统


但请注意,这是一种边缘黑客行为。您的shell将消亡,并用运行在同一进程中的python脚本替换自己。python脚本对环境进行更改,并用shell替换自身,再次返回,仍然处于相同的过程中。这意味着,如果您在上一个shell会话中有其他一些未保存和未报告的本地数据或环境,它将不会保留到新的。这还意味着rc和概要文件脚本将再次运行(通常不是问题)。

如果使用单引号,则不必转义美元符号:
alias mcd='cd$(/path/to/my_cd.py)
os.execl(sys.argv[1], sys.argv[2])