简体   繁体   English

为什么 cd 命令在我的 shell 程序中不起作用?

[英]Why doesn't the cd command work in my shell program?

When I created my own shell, I am not able to execute cd command which I am able to do in the Linux shell.当我创建自己的 shell 时,我无法执行我可以在 Linux shell 中执行的 cd 命令。 Why is that?为什么?

That's probably because the cd command has to be built into the shell, not something external and executed.这可能是因为cd命令必须内置到 shell 中,而不是外部并执行的命令。 If an external command changed directory, it has no effect on the parent shell.如果一个外部命令改变了目录,它对父 shell 没有影响。 (Even though there is usually a command /bin/cd or /usr/bin/cd on Linux and macOS systems, executing it changes the directory for that process, but has no effect on the process that invoked it.) (即使 Linux 和 macOS 系统上通常有/bin/cd/usr/bin/cd命令,执行它会更改该进程的目录,但对调用它的进程没有影响。)


I do not understand the line "If the external command changed directory, it has no effect on the parent shell".我不明白“如果外部命令更改了目录,它对父 shell 没有影响”这一行。

Normally, when a shell executes a command, it does fork() and the child process uses exec() to execute the command entered by the user.通常,当shell执行命令时,它会执行fork() ,子进程使用exec()来执行用户输入的命令。 For example, if the entered command is ' ls / ', the shell arranges to execute /bin/ls with two arguments, ls and / .例如,如果输入的命令是“ ls / ”,shell 会安排执行带有两个参数的/bin/lsls/ However, if the command selected executes the chdir() system call, that affects the child process, but does not affect the parent shell.但是,如果所选命令执行chdir()系统调用,则会影响子进程,但不会影响父 shell。 So, the shell has to handle the cd command itself, not via fork() and exec() .因此,shell 必须自己处理cd命令,而不是通过fork()exec()

Note that in DOS, a .BAT file can do cd and it affects the cmd.exe process.请注意,在 DOS 中, .BAT文件可以执行cd并影响cmd.exe进程。 This does not happen in Unix — a child process cannot affect the current directory of the parent process.这在 Unix 中不会发生——子进程不能影响父进程的当前目录。

Jonathan Leffler explained why this was, but I wanted to offer a workaround in case you actually need this functionality. Jonathan Leffler 解释了为什么会这样,但我想提供一种解决方法,以防您确实需要此功能。 In bash (you didn't specify, so I'll assume), the source command can be used to execute a shell script in the CURRENT shell process.在 bash 中(你没有指定,所以我假设), source命令可用于在 CURRENT shell 进程中执行 shell 脚本。 I use something similar to the below (though more comprehensive), along with a shell alias, to change to project directories and automagically set up the environment:我使用类似于下面的内容(虽然更全面)以及 shell 别名来更改项目目录并自动设置环境:

~:$ cat $HOME/bin/goproj
#!/bin/bash
...
export SOMEVAR=someval
cd /home/foo/src/projects/"$1"
...

~:$ alias gp
alias gp="source $HOME/bin/goproj"

~:$ gp foo
~/src/projects/foo:$ echo $SOMEVAR
someval
~/src/projects/foo:$

Using this type of setup, you can modify the current shell with whatever exists in the script you're sourcing.使用这种类型的设置,您可以使用您正在采购的脚本中存在的任何内容修改当前 shell。 Note that if you ran 'goproj' directly, it wouldn't work for the same problem you're already experiencing;请注意,如果您直接运行 'goproj',它将无法解决您已经遇到的相同问题; you must call it with source .你必须用source调用它。

This is as simple as :这很简单:

  • cd is not a command. cd不是命令。

Try this :试试这个:

-- whereis ls -- whereis ls

-- whereis cd -- whereis cd

(See the difference) (看区别)

  • cd is property of the shell, so if you are making a shell then you have to support cd . cd是 shell 的属性,所以如果你正在制作一个 shell,那么你必须支持cd

See it this way, when ls is executed then it needs to know the pwd.这样看,当执行 ls 时,它需要知道密码。 So, it your custom shell that would handle the directory.因此,您的自定义 shell 将处理该目录。 So, its the shell that has to support cd.所以,它的外壳必须支持 cd。

I think I made myself clear.我想我已经说清楚了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM