是否可以通过编程方式更改父Shell的工作目录?


8

我想编写一些代码以允许我切换到通常访问的某些目录。说这个程序是mycd,并且/a/very/long/path/name是我要转到的目录。

所以我可以简单地键入mycd 2而不是cd /a/very/long/path/name。在这里我假设mycd知道2是指/a/very/long/path/name。也可能有mycd 1mycd 3,...等等。

问题是我必须编写mycd为shell脚本并键入. mycd 2以执行所需的操作,因为否则该脚本将在子脚本中执行,而子脚本不会更改我实际上关心的父shell。

我的问题是:

  • 我可以不用使用它source吗?因为. mycd假定mycd必须是一个shell脚本,并且这可能还会引入一些我不需要的功能。

  • 我可以用其他一些编程语言实现它吗?

Answers:


23

创建mycd一个函数,以便该cd命令在您当前的shell中执行。将其保存在〜/ .bashrc文件中。

function mycd {
    if (( $# == 0 )); then
        echo "usage: $FUNCNAME [1|2|3|...]"
        return
    fi
    case $1 in
        1) cd /tmp ;;
        2) cd /a/very/long/path/name ;;
        3) cd /some/where/else ;;
        *) echo "unknown parameter" ;;
    esac
}

谢谢,没有考虑使用函数,这只是启用了所有功能:现在我可以mycd传递$@给我喜欢的任何程序了。
Javran 2014年

确保引用"$@"以正确处理所有包含空格的参数。
glenn jackman 2014年

9

您不能从另一个进程更改Shell的当前目录。只有进程本身可以更改其自己的当前目录。这也适用于其他一些特征,例如环境变量和文件描述符。

实际上,可以通过使另一个进程chdir通过ptrace系统调用执行系统调用来影响另一个进程的当前目录,这使调试器可以工作。但是,如果该进程维护某些必须与实际当前目录一致的内部数据结构,则该程序很可能崩溃。对于外壳,这种方法没有机会起作用。

您需要安排您的代码由Shell本身执行。进行程序的正常方式是使它成为一个shell函数并将它存储在你的~/.bashrc。如果这是不可能的,例如因为要分发的代码,则编写一个包含函数定义的shell源文件,并告诉人们让他们的交互式shell使用.command读取您的文件。


1
实际上有机会使它“起作用”,但是它是不平凡的,容易出错的,应该不惜一切代价避免。要显示它实际上是“可能”,认为这是shell脚本,如果母公司是击:ws=$1; gdb -p $(ps h -o ppid -p $$) -ex "call chdir(\"$wd\")" -ex "call set_working_directory(\"$wd\")" -ex detach -ex q -batch。执行为braindead-cd-parent /。您将看到pwd返回/,等等也是如此ls。但是提示(PS1)仍然不变,人们的眼睛受到伤害等。因此,即使有可能也不要这样做。
Lekensteyn 2014年

1
@Lekensteyn这就是ptrace我提到的方法。它在不太关心当前目录的程序上效果很好。在外壳程序中,很多事情(PWD变量,提示等)将变得错误,并且外壳程序可能崩溃或发生其他行为。
吉尔(Gilles)'所以别再邪恶了'

5

正如您自己指出的那样,shell脚本始终在子shell中执行,这不会影响其父shell。

但是,您可以...

  • 使用别名:
    alias mycd2='cd /a/very/long/path/name'
  • 让您的脚本1输出有效的shell命令...

    #!/bin/bash
    if [ "x$1" = "x2" ]
    then
        echo "cd /a/very/long/path/name"
    fi

    ...并执行其输出: $(mycd 2)

1:您可能想使用case语句而不是if示例中的条件。


5
别名是可传递的。脚本是他已经遇到的相同问题。这个问题尖叫着外壳功能。
Ricky Beam
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.