我有一个 Makefile,其中有一个sshfs
命令,后跟一个cd
命令:
mr: # mount-remote
sshfs -p 5022 -o nonempty [email protected]:mnt /home/julien/myworking_path
cd ./working_directory_mwe1/wk_subd_mwe2/
第一个命令 sshfs 运行良好,正确挂载了两个端点。但是,cd 命令不会更改目录。然后我必须手动重新输入。如果我手动输入,它就可以正常工作,但我希望在输入命令时完成它mr
。
我尝试了以下操作,考虑到这可能是因为我在执行时终端连接了 2 秒,sshfs
但这也不起作用。我尝试cd
每秒重新运行一次,直到它起作用。
mr: # mount-remote
sshfs -p 5022 -o nonempty [email protected]:mnt /home/julien/myworking_path
until cd ./working_directory_mwe1/wk_subd_mwe2/ ; do sleep 1 ; done
感谢您的热心帮助 :)
编辑:我忘了指定我尝试的最小工作目录cd
正是端点的目录,实际上,我意识到我的目标是:
mr: # mount-remote
sshfs -p 5022 -o nonempty [email protected]:mnt /home/julien/myworking_path
cd /home/julien/myworking_path/some_sub_dir1/som_sub_dir2
答案1
但是,cd 命令不会改变目录。
确实如此 - 但它只影响由“make”生成的临时 shell 子进程,而不影响它们上方的交互式 shell。
“当前目录”不是终端范围的参数 –每个过程都有自己的当前目录,并且子进程中对它的更改永远不会向上传播(它们只能由更改后创建的新进程继承)。
xterm
└─ bash (interactive)
└─ make mr
├─ /bin/sh -c "sshfs -p ..."
│ └─ sshfs -p ...
└─ /bin/sh -c "cd ..."
这意味着您在 Makefile 中执行的任何操作都不会在make
退出后直接影响父 shell,这同样适用于用任何其他语言编写的脚本。(环境变量也以相同的方式工作。)
实现这一目标的唯一方法是将mr
(即单独的“mr”,不再是“make mr”)变成一个 shell别名或 shell功能– 两者都是在 shell 内部执行的。
~/.bashrc
您可以在或中定义函数~/.zshrc
:
mr() {
sshfs foo:mnt ~/working_path
cd ~/working_path/something
}
请注意,调用 shell 函数时不必输入括号,定义它们时才需要。一旦定义,它们的行为就像常规命令一样,只需调用mr
. (也可以看看用其他方式来定义它们。
如果函数足够短小简单(特别是不需要通过 $1 等接受参数),那么它可以是一个别名——别名也能够更改当前目录:
alias mr='sshfs foo:mnt ~/working_path && cd ~/working_path/something'
最重要的是,常规 make 会运行分离shell 子进程,因此即使同一 Make 配方中的其他命令也不会受到影响。
如果您想要cd
影响 Make 配方,则需要使用\
延续将所有配方行连接成单个“逻辑行”,如下所示:
mr:
sshfs foo:mnt ~/myworking_path
cd ./working_directory_mwe1/wk_subd_mwe2/ && \
pwd && ls && echo "This happens in the new directory..."
pwd && ls && echo "...this is back in the old one."
...或者使用 GNU Make 特定的.ONESHELL:
特殊目标:
.ONESHELL:
mr:
sshfs foo:mnt ~/myworking_path
cd ./working_directory_mwe1/wk_subd_mwe2/
pwd; ls; echo "This time the directory change did carry over."