diff --git a/src/app.rs b/src/app.rs index f42ac8cac..20998cb97 100644 --- a/src/app.rs +++ b/src/app.rs @@ -257,6 +257,14 @@ pub fn build_app() -> App<'static, 'static> { .hidden_short_help(true) .overrides_with("show-errors"), ) + .arg( + arg("base-directory") + .long("base-directory") + .takes_value(true) + .value_name("path") + .number_of_values(1) + .hidden_short_help(true), + ) .arg(arg("pattern")) .arg( arg("path-separator") @@ -443,5 +451,8 @@ fn usage() -> HashMap<&'static str, Help> { , "(hidden)" , "Provide paths to search as an alternative to the positional argument. \ Changes the usage to `fd [FLAGS/OPTIONS] --search-path --search-path []`"); + doc!(h, "base-directory" + , "(hidden)" + , "Change current working directory of the fd process to provided path."); h } diff --git a/src/main.rs b/src/main.rs index 426eb080d..e17dc7d12 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,6 +44,23 @@ fn main() { let checked_args = transform_args_with_exec(env::args_os()); let matches = app::build_app().get_matches_from(checked_args); + // Set the current working directory of the process + if let Some(base_directory) = matches.value_of("base-directory") { + let basedir = Path::new(base_directory); + if !fshelper::is_dir(basedir) { + print_error_and_exit!( + "The '--base-directory' path ('{}') is not a directory.", + basedir.to_string_lossy() + ); + } + if let Err(e) = env::set_current_dir(basedir) { + print_error_and_exit!( + "Could not set '{}' as the current working directory: {}", + basedir.to_string_lossy(), e + ); + } + } + // Get the search pattern let pattern = matches.value_of("pattern").unwrap_or(""); diff --git a/tests/tests.rs b/tests/tests.rs index d9c0130a8..723725266 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1350,3 +1350,53 @@ fn test_custom_path_separator() { one=two=three=directory_foo", ); } + +#[test] +fn test_base_directory() { + let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES); + + te.assert_output( + &["--base-directory", "one"], + "b.foo + two + two/c.foo + two/C.Foo2 + two/three + two/three/d.foo + two/three/directory_foo", + ); + + te.assert_output( + &["--base-directory", "one/two", "foo"], + "c.foo + C.Foo2 + three/d.foo + three/directory_foo", + ); + + // Explicit root path + te.assert_output( + &["--base-directory", "one", "foo", "two"], + "two/c.foo + two/C.Foo2 + two/three/d.foo + two/three/directory_foo", + ); + + // Ignore base directory when absolute path is used + let (te, abs_path) = get_test_env_with_abs_path(DEFAULT_DIRS, DEFAULT_FILES); + let abs_base_dir = &format!("{abs_path}/one/two", abs_path = &abs_path); + te.assert_output( + &["--base-directory", &abs_base_dir, "foo", &abs_path], + &format!( + "{abs_path}/a.foo + {abs_path}/one/b.foo + {abs_path}/one/two/c.foo + {abs_path}/one/two/C.Foo2 + {abs_path}/one/two/three/d.foo + {abs_path}/one/two/three/directory_foo", + abs_path = &abs_path + ), + ); + +}