从Go更改父shell目录

acl*_*kay 0 go

我怎么能写一个像'cd'那样的Go程序呢?

我试过运行一个命令,但它没有用.

func main() {
    cmd := exec.Command("cd", "/media/")
    err := cmd.Run()
    log.Printf("Command finished with error: %v", err)
}
Run Code Online (Sandbox Code Playgroud)

Bas*_*tch 5

我怎么能写一个像'cd'那样的Go程序呢?

在POSIX系统上不可能的(即使使用任何其他编程语言).

因为每个进程(包括父shell进程)都有自己的当前工作目录.因此cd必须是一个内置的shell(调用由shell进程本身完成的chdir(2)系统调用),它不能通过某些可执行文件完成,因为shell会分配一个新进程来运行每个命令(使用一些可执行文件,即不是内置的).

阅读一些优秀的Unix或Linux编程书,例如ALP,以获得解释.一本关于操作系统的好书,例如操作系统:三个简单的部分可以解释你为什么会这样(并且在类似POSIX或类Unix的系统中无法合理地说明).

您的代码正在分支(使用cmd.Run)一个新进程,并且子进程更改其工作目录.另请参见fork(2)&execve(2)&path_resolution(7).

要在Go代码中调用 chdir(2)系统调用,请使用os.Chdir.这只会影响你的进程(以及fork(2)创建的所有未来子进程,它继承了父进程的工作目录),当然也不会改变父进程的工作目录(通常是你的shell) .

要获取当前进程的当前工作目录(使用getcwd(2)系统调用),请使用os.GetwdGo代码(并查看代码).

在Linux上,您可以使用/proc/(请参阅proc(5)了解详细信息)来查询其他进程的工作目录.例如,ls -l /proc/$$/cwd在shell中运行.在Go代码中,你将在类似的路径上使用os.Readlink/proc/1234/cwd.当然你不能改变其他进程的工作目录(你可以改变的唯一工作目录是你自己的进程,使用chdir( 2))

正如David Budsworth评论的那样,你可以采用一种奇怪的约定:1.你的prog程序在标准输出上写一个有效的(并且适当引用shell)目录路径,而不是别的.2.你总是prog命令替换中使用该程序,例如cd $(prog args...)(它可能成为shell函数别名的主体等等),然后你的shell(不是你的prog)会改变目录作为程序的输出.

  • 可以通过别名来做'alias gcd = cd [backtick] goprog foo [backtick]`(不知道如何在注释中输入文字反引号,因为它会产生一个代码片段.但是这将使用`foo`运行`goprog`作为一个参数,然后`cd`到任何输出 (2认同)