How to capture directory change such as cd in Command

Hello all,

I'm using Command to change directory on mac, I was wondering if it was possible to find the new full directory path from output or command, but the path/cwd does not seem to be updated after output() has been called. Below is the code I'm using, I get "no dir" if I don't specify anything, even though there must be a cwd and it must be known to the process.

use std::{path::Path, process::Command};

fn main() {
    let mut command = Command::new("cd");
    command.arg("target");
    // command.current_dir("/"); // <-- Doesn't seem to do anything

    let mut cwd = command.get_current_dir();
    match cwd {
        Some(x) => println!("{x:?}"),
        None => println!("no dir"),
    }

    let output = command.output();
    
    cwd = command.get_current_dir();
    match cwd {
        Some(x) => println!("{x:?}"),
        None => println!("no dir"),
    }
}

cd is a shell command, not a binary. You don't need Command to change your processes working directory. Use std::env::set_current_dir to change the CWD of your process (and use std::env::current_dir to query it).

The current directory methods on Command are for getting / setting the directory that the Command process will be started in (or None if they'll be started in this process's CWD). Not querying a process's CWD. (Additionally, the Command process has ended by the time output returns.)

3 Likes

What you are seeing is consistent with the documentation:

Returns the working directory for the child process.

This returns None if the working directory will not be changed.

As you are constructing the Command without instructing it to change the current directory, the command will be run with the current directory unchanged. Even if cd was a freestanding command (which it isn't; see @quinedot's reply), that None only signifies that it would be run with your program's current directory as its current directory.

Thanks for the replies they're very helpful. Maybe I should try to explain why I'm doing this.

I was curious to see how complex making a little pseudoterminal would be in Rust.
Overall it's pretty simple and works great by taking the user input, parsing, and turning into Command. But if I type in cd <target> or something more complex I'd like to know where the user currently has moved to in a directory after the operation. I could parse all "cd ..." but I don't think that's a very extensive solution.

There's a reason why cd is a built-in command in all shells: because it's impossible to modify the environment of other processes.

4 Likes