5

I have a Makefile with a sshfs command followed with a cd command:

mr: # mount-remote
        sshfs -p 5022 -o nonempty [email protected]:mnt /home/julien/myworking_path
        cd ./working_directory_mwe1/wk_subd_mwe2/

The first command, sshfs works like a charm and correctly mounts both endpoint. However, the cd command does not change directory. I then have to re-type it manually. It then works if I type in manually, but I want it to be done when typing the mr command.

I tried the following instead having in mind that it may be because I have my terminal connecting for 2 seconds while executing the sshfs but that did not work either. I tried to re-run cd every second until it works.

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

Thank you for your kind help :)

EDIT: I forgot to specify that the minimal working directories I tried to cd is exactly the one at the endpoint, actually, I realized my aim is rather:

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
3
  • 3
    In a Makefile, each line is run in a different shell. If you want to run something in a different directory, you need to cd /dir && something.
    – choroba
    Commented Feb 9, 2022 at 18:08
  • Thank you for your replies. I tried cd /home/julien/myworking_path/working_directory_mwe1/wk_subd_mwe2/ instead as suggested by @Giacomo1968 but it did not succeed neither. I edited my question, I forgot a, maybe important, point
    – JKHA
    Commented Feb 9, 2022 at 18:12
  • Yes, sorry, wrote too fast, comment edited. I think @user1686's answer has it right
    – JKHA
    Commented Feb 9, 2022 at 18:16

1 Answer 1

17

However, the cd command does not change directory.

It does – but it only affects the temporary shell subprocess spawned by 'make', not the interactive shell above them.

The "current directory" is not a terminal-wide parameter – each process has its own current directory, and changes to it in child processes never propagate upwards (they can only be inherited down by new processes created after the change).

xterm
 └─ bash (interactive)
     └─ make mr
         ├─ /bin/sh -c "sshfs -p ..."
         │   └─ sshfs -p ...
         └─ /bin/sh -c "cd ..."

This means that nothing you do in the Makefile can directly affect the parent shell after make exits, and the same applies to scripts written in any other language. (Environment variables work the same way, too.)

The only way to make this work is to turn mr (that is, "mr" alone, no longer "make mr") into a shell alias or a shell function – both of which are executed internally to the shell.

Functions can be defined in your ~/.bashrc or ~/.zshrc:

mr() {
    sshfs foo:mnt ~/working_path
    cd ~/working_path/something
}

Note that you don't have to type the parenthesis when invoking shell functions, only when defining them. Once defined they behave like regular commands and are invoked as just mr. (See also other ways to define them.)

If the function is sufficiently short and simple (and in particular, if doesn't need to accept arguments through $1 etc.), then it can be an alias instead – aliases are able to change the current directory as well:

alias mr='sshfs foo:mnt ~/working_path && cd ~/working_path/something'


On top of that, regular make runs each line in a separate shell subprocess, so even further commands in the same Make recipe remain unaffected.

If you had instead wanted the cd to affect the Make recipe, you would need to either join all recipe lines into a single "logical line" using \ continuations, like this:

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."

...or use the GNU Make-specific .ONESHELL: special target:

.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."
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .