无需“shell 过程”或“获取脚本”即可从脚本更改目录

无需“shell 过程”或“获取脚本”即可从脚本更改目录

我知道我能做什么外壳程序或者获取脚本而不是运行它cd我正在使用的外壳。我想知道的就在那里任何到“父外壳”的方式cd(不确定这是否是正确的短语)。

#!/bin/sh
# This is script.sh
cd $1
pwd

这是一些输出。 (笔记:这不是确切的输出,我只是通过删除不必要的细节来缩短它。我在 shell 中输入的行以 开头>。)

> mkdir foo
> ./script.sh foo
/home/myName/foo
> pwd
/home/myName

据我了解,这是预期的行为。这是我“获取”脚本的情况。

> . ./script.sh foo
/home/myName/foo
> pwd
/home/myName/foo

如果不获取脚本也不将其设为 shell 过程,有什么方法可以./script.sh foo在目录中使用的 shell 中输入结果吗/home/myName/foo

答案1

不会,因为当您将脚本调用为 时./script.sh foo,它会启动一个子 shell 来为您运行该脚本。当该子 shell 退出时,您将返回到启动该脚本时所​​在的目录。不过,您可以通过使用执行如下操作的脚本来伪造此行为:

#!/bin/bash
cd $1
bash

更改目录后,这将使您进入子 shell,然后您必须exit返回到原始 shell。

如果你改为最后一行:

exec bash

您不必退出新 shell,因为新 shell 将替换旧 shell。然而,这样做仍然是一个丑陋的黑客行为(恕我直言)。

答案2

简单的答案是否定的——这是不可能的。

但是,如果您绝望,您可能会找到一些解决方法。

最简单的方法是当您只需要几个目录时提前知道(在父 shell 中)脚本可能尝试cd进入的位置。在这种情况下,您可以为从脚本发送的某些信号设置陷阱。

~ $ cat script
#!/bin/bash
kill -s SIGINT "$PPID"

~ $ trap 'cd /tmp' SIGINT
~ $ ./script
/tmp $

执行此操作的一种更复杂的方法是将脚本中的命令写入父 shell 标准输入。描述了程序(相当复杂)这里,但最简单的情况(提前定义目录)也很简单:

~ $ cat script
#!/bin/bash
printf '\e[5n' >/proc/"$PPID"/fd/0

~ $ bind '"\e[0n": "cd /tmp\n"'
~ $ ./script
/tmp $

如果您想将目录名称作为参数从脚本传递到父 shell,我建议您研究上面链接中的答案。

答案3

你可以试试:

gdb --batch -ex 'call chdir("/some/dir")' -p "$PPID"

但我预计大多数 shell 在当前目录发生变化时都会感到困惑。

顺便说一句,在 shell 语法中,您需要在变量周围加上引号并将--选项与参数分开。另请参阅cd未通过时的特殊行为-P。所以你的代码应该更像是:

#! /bin/sh -
cd -P -- "$1"

例如,相当于int main(int argc, char*argv[]){chdir(argv[1])}C 语言(在更改另一个进程的当前目录时仍然无效)

答案4

脚本在子 shell 中运行,任何环境更改(目录和变量)都是该进程的本地更改,并在进程退出(或以其他方式交回控制权)时恢复到调用进程的环境更改。

您可以运行命令在当前外壳中(因此它们的效果仍然存在)通过获取脚本 ( . here/is/the/script) 或定义 shell 函数。 Shell 函数可能非常复杂,而且最重要的是,它们是在当前 shell 进程中执行的。并非所有 shell 都支持函数(bash 支持)。

相关内容