我正在尝试实现我自己版本的'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
的源bash脚本中将调用包装到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
关于如何让它发挥作用的任何想法?是否可以从python脚本更改我的交互式shell的当前目录?
答案 0 :(得分:7)
将您的源代码bash
更改为:
#! /bin/bash
function my_cd() {
cd `/path/to/my_cd.py`
}
和您的Python代码在cosmetic
上完成所有sys.stderr
输出(向用户,菜单等发送消息),最后代替os.chdir
, print
(到sys.stdout
)目录应该更改的路径。
答案 1 :(得分: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$
答案 2 :(得分:2)
这不可能。父进程看不到对工作目录的更改。最多可以让Python脚本打印要更改的目录,然后让源脚本实际更改为该目录。
答案 3 :(得分:2)
它的价值,因为这个问题也标记为“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
现在,此脚本必须是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脚本,它首先执行dir选择,然后在cd完成后潜入python程序。
答案 4 :(得分: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会话中有一些其他本地未保存和未导出的数据或环境,它将不会持久保存到新的。这也意味着rc和profile脚本将再次运行(通常不是问题)。