Repository: sharkdp/fd (language: rust)

Issue:
fd is vulnerable to filenames with leading dashes
**Describe the bug you encountered:**  When piping relative paths from `fd` to utilities like `xargs`, the program does not return paths, but rather file names.  For instance, in a directory containing `foo.txt`, the command `fd -t f -0 | xargs -0 -I% rm %` passes `foo.txt` to xargs rather than `./foo.txt`.  

If the directory contains files with leading dashes, such as the file `-rf`, commands like `rm` interpret this as options rather than a valid path.  Certain commands have the end-of-options `--` parameter, but not all do, and the burden falls on the user to use `--`.  `find` fixes this problem by always returning absolute or relative paths; returning `./-rf` would not pose a problem for further processing.

Filenames with dashes are not limited to deliberately malicious constructs.  I have found program-generated files in `.config` folders full of leading dashes, as well as media files saved by id, whose id happened to have a leading dash.
 
**Describe what you expected to happen:**  when searching by relative paths, `fd` should return paths, i.e. filenames prefixed by `./` to avoid problems like the above; especially when the output of `fd` is in a pipeline.

**What version of `fd` are you using?** `fd 8.2.1`

**Which operating system / distribution are you on?**
Linux 5.11.12-arch1-1 x86_64

LSB Version:	1.4
Distributor ID:	Arch
Description:	Arch Linux
Release:	rolling
Codename:	n/a


Discussion / hints:
You could use the `--absolute-path` or `-a` option to have `fd` output full paths instead of just the filename.
Certainly; the problem is with a third user who may be unaware of the leading dash issue.  If `fd` does not want to return relative paths, should the documentation emphasize to always use `-a` when using `fd` in a pipe, or even enforce `-a` in such a case?
Thank you for reporting this. I agree that we should fix this somehow. Unfortunately, this will cause breaking changes, as some people probably rely on the current format of passing arguments (I certainly do).

Using absolute paths would be an easy way out, but I don't think it's desirable, especially for commands where the user sees the paths. I'd rather try to follow `find` here.
> Certainly; the problem is with a third user who may be unaware of the leading dash issue. If `fd` does not want to return relative paths, should the documentation emphasize to always use `-a` when using `fd` in a pipe, or even enforce `-a` in such a case?

BTW, in such cases I like to link to a [superb article] by David A. Wheeler about dangerous filenames and managing the problem. If there is place for a "further reading" link I propose to add this one.

[superb article]: https://dwheeler.com/essays/filenames-in-shell.html
The same problem actually appears with `fd`s builtin `-x`/`-X` as well.

how to (safely) reproduce:
```bash
> mkdir /tmp/issue-760; cd /tmp/issue-760
> touch -- '-e' 'foo.txt'
> fd -X echo
foo.txt                                        # <-- should include '-e' as well
> fd -0 | xargs -0 echo
foo.txt                                        # <-- same

> fd -a -X echo # workaround
/tmp/issue-760/-e /tmp/issue-760/foo.txt
```

I think we could fix this by:
- prepending `./` for all relative paths when using `-x`/`-X`.
- prepending `./` for all relative paths when the output is a non-interactive terminal

This way, we can leave the normal (interactive console) `fd` output unmodified.
I'm messing around with some changes for this, The same behavior should apply to Windows, assuming it's not a path that already starts with a `Component::Prefix`, right? 
  
> I'm messing around with some changes for this, The same behavior should apply to Windows, assuming it's not a path that already starts with a `Component::Prefix`, right?

yes. whenever it's a relative path (I guess). Might make sense to validate that the same bug appears on Windows as well.
~I'm not too familiar with Windows command line stuff so I might be doing something wrong, but `fd -X echo` outputs 'command not found', even though plain `echo whatever` does work (same on both cmd and powershell).~* Other than that, I think all that would need to change is the `filesystem::strip_current_dir` calls during command generation and when printing.

#538 describes what I was missing, will try testing some more*

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f3b4e3cfd..529cd5276 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@
 
 ## Bugfixes
 
+- Always show the `./` prefix for search results unless the output is a TTY or `--strip-cwd-prefix` is set, see #760 and #861 (@jcaplan)
 - Set default path separator to `/` in MSYS, see #537 and #730 (@aswild)
 - fd cannot search files under a RAM disk, see #752
 - fd doesn't show substituted drive on Windows, see #365
diff --git a/src/app.rs b/src/app.rs
index ee514b40f..dd4282b27 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -704,6 +704,17 @@ pub fn build_app() -> App<'static, 'static> {
                          argument. Changes the usage to `fd [FLAGS/OPTIONS] --search-path <path> \
                          --search-path <path2> [<pattern>]`",
                 ),
+        )
+        .arg(
+            Arg::with_name("strip-cwd-prefix")
+                .long("strip-cwd-prefix")
+                .conflicts_with_all(&["path", "search-path"])
+                .hidden_short_help(true)
+                .help("strip './' prefix from non-tty outputs")
+                .long_help(
+                    "By default, relative paths are prefixed with './' when the output goes to a non \
+                     interactive terminal (TTY). Use this flag to disable this behaviour."
+                )
         );
 
     if cfg!(unix) {
diff --git a/src/config.rs b/src/config.rs
index c11f88bab..5a7171483 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -113,4 +113,7 @@ pub struct Config {
 
     /// The maximum number of search results
     pub max_results: Option<usize>,
+
+    /// Whether or not to strip the './' prefix for search results
+    pub strip_cwd_prefix: bool,
 }
diff --git a/src/exec/mod.rs b/src/exec/mod.rs
index fc22e6f94..3f93acdb4 100644
--- a/src/exec/mod.rs
+++ b/src/exec/mod.rs
@@ -14,7 +14,6 @@ use once_cell::sync::Lazy;
 use regex::Regex;
 
 use crate::exit_codes::ExitCode;
-use crate::filesystem::strip_current_dir;
 
 use self::command::execute_command;
 use self::input::{basename, dirname, remove_extension};
@@ -144,8 +143,6 @@ impl CommandTemplate {
         out_perm: Arc<Mutex<()>>,
         buffer_output: bool,
     ) -> ExitCode {
-        let input = strip_current_dir(input);
-
         let mut cmd = Command::new(self.args[0].generate(&input, self.path_separator.as_deref()));
         for arg in &self.args[1..] {
             cmd.arg(arg.generate(&input, self.path_separator.as_deref()));
@@ -177,7 +174,7 @@ impl CommandTemplate {
                 // A single `Tokens` is expected
                 // So we can directly consume the iterator once and for all
                 for path in &mut paths {
-                    cmd.arg(arg.generate(strip_current_dir(path), self.path_separator.as_deref()));
+                    cmd.arg(arg.generate(path, self.path_separator.as_deref()));
                     has_path = true;
                 }
             } else {
diff --git a/src/main.rs b/src/main.rs
index 172d570ed..cb6dfa8f9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -380,6 +380,9 @@ fn construct_config(matches: clap::ArgMatches, pattern_regex: &str) -> Result<Co
                     None
                 }
             }),
+        strip_cwd_prefix: (!matches.is_present("path")
+            && !matches.is_present("search-path")
+            && (interactive_terminal || matches.is_present("strip-cwd-prefix"))),
     })
 }
 
diff --git a/src/output.rs b/src/output.rs
index 194cb2adc..5fae330f7 100644
--- a/src/output.rs
+++ b/src/output.rs
@@ -22,10 +22,10 @@ pub fn print_entry(
     config: &Config,
     wants_to_quit: &Arc<AtomicBool>,
 ) {
-    let path = if entry.is_absolute() {
-        entry
-    } else {
+    let path = if config.strip_cwd_prefix {
         strip_current_dir(entry)
+    } else {
+        entry
     };
 
     let r = if let Some(ref ls_colors) = config.ls_colors {


Test patch:
diff --git a/tests/tests.rs b/tests/tests.rs
index 54b4ecce4..807b91bf7 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -61,18 +61,18 @@ fn create_file_with_size<P: AsRef<Path>>(path: P, size_in_bytes: usize) {
 fn test_simple() {
     let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);
 
-    te.assert_output(&["a.foo"], "a.foo");
-    te.assert_output(&["b.foo"], "one/b.foo");
-    te.assert_output(&["d.foo"], "one/two/three/d.foo");
+    te.assert_output(&["a.foo"], "./a.foo");
+    te.assert_output(&["b.foo"], "./one/b.foo");
+    te.assert_output(&["d.foo"], "./one/two/three/d.foo");
 
     te.assert_output(
         &["foo"],
-        "a.foo
-        one/b.foo
-        one/two/c.foo
-        one/two/C.Foo2
-        one/two/three/d.foo
-        one/two/three/directory_foo",
+        "./a.foo
+        ./one/b.foo
+        ./one/two/c.foo
+        ./one/two/C.Foo2
+        ./one/two/three/d.foo
+        ./one/two/three/directory_foo",
     );
 }
 
@@ -80,17 +80,17 @@ fn test_simple() {
 #[test]
 fn test_empty_pattern() {
     let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);
-    let expected = "a.foo
-    e1 e2
-    one
-    one/b.foo
-    one/two
-    one/two/c.foo
-    one/two/C.Foo2
-    one/two/three
-    one/two/three/d.foo
-    one/two/three/directory_foo
-    symlink";
+    let expected = "./a.foo
+    ./e1 e2
+    ./one
+    ./one/b.foo
+    ./one/two
+    ./one/two/c.foo
+    ./one/two/C.Foo2
+    ./one/two/three
+    ./one/two/three/d.foo
+    ./one/two/three/directory_foo
+    ./symlink";
 
     te.assert_output(&["--regex"], expected);
     te.assert_output(&["--fixed-strings"], expected);
@@ -209,17 +209,17 @@ fn test_regex_searches() {
 
     te.assert_output(
         &["[a-c].foo"],
-        "a.foo
-        one/b.foo
-        one/two/c.foo
-        one/two/C.Foo2",
+        "./a.foo
+        ./one/b.foo
+        ./one/two/c.foo
+        ./one/two/C.Foo2",
     );
 
     te.assert_output(
         &["--case-sensitive", "[a-c].foo"],
-        "a.foo
-        one/b.foo
-        one/two/c.foo",
+        "./a.foo
+        ./one/b.foo
+        ./one/two/c.foo",
     );
 }
 
@@ -230,21 +230,21 @@ fn test_smart_case() {
 
     te.assert_output(
         &["c.foo"],
-        "one/two/c.foo
-        one/two/C.Foo2",
+        "./one/two/c.foo
+        ./one/two/C.Foo2",
     );
 
-    te.assert_output(&["C.Foo"], "one/two/C.Foo2");
+    te.assert_output(&["C.Foo"], "./one/two/C.Foo2");
 
-    te.assert_output(&["Foo"], "one/two/C.Foo2");
+    te.assert_output(&["Foo"], "./one/two/C.Foo2");
 
     // Only literal uppercase chars should trigger case sensitivity.
     te.assert_output(
         &["\\Ac"],
-        "one/two/c.foo
-        one/two/C.Foo2",
+        "./one/two/c.foo
+        ./one/two/C.Foo2",
     );
-    te.assert_output(&["\\AC"], "one/two/C.Foo2");
+    te.assert_output(&["\\AC"], "./one/two/C.Foo2");
 }
 
 /// Case sensitivity (--case-sensitive)
@@ -252,13 +252,13 @@ fn test_smart_case() {
 fn test_case_sensitive() {
     let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);
 
-    te.assert_output(&["--case-sensitive", "c.foo"], "one/two/c.foo");
+    te.assert_output(&["--case-sensitive", "c.foo"], "./one/two/c.foo");
 
-    te.assert_output(&["--case-sensitive", "C.Foo"], "one/two/C.Foo2");
+    te.assert_output(&["--case-sensitive", "C.Foo"], "./one/two/C.Foo2");
 
     te.assert_output(
         &["--ignore-case", "--case-sensitive", "C.Foo"],
-        "one/two/C.Foo2",
+        "./one/two/C.Foo2",
     );
 }
 
@@ -269,14 +269,14 @@ fn test_case_insensitive() {
 
     te.assert_output(
         &["--ignore-case", "C.Foo"],
-        "one/two/c.foo
-        one/two/C.Foo2",
+        "./one/two/c.foo
+        ./one/two/C.Foo2",
     );
 
     te.assert_output(
         &["--case-sensitive", "--ignore-case", "C.Foo"],
-        "one/two/c.foo
-        one/two/C.Foo2",
+        "./one/two/c.foo
+        ./one/two/C.Foo2",
     );
 }
 
@@ -287,25 +287,25 @@ fn test_glob_searches() {
 
     te.assert_output(
         &["--glob", "*.foo"],
-        "a.foo
-        one/b.foo
-        one/two/c.foo
-        one/two/three/d.foo",
+        "./a.foo
+        ./one/b.foo
+        ./one/two/c.foo
+        ./one/two/three/d.foo",
     );
 
     te.assert_output(
         &["--glob", "[a-c].foo"],
-        "a.foo
-        one/b.foo
-        one/two/c.foo",
+        "./a.foo
+        ./one/b.foo
+        ./one/two/c.foo",
     );
 
     te.assert_output(
         &["--glob", "[a-c].foo*"],
-        "a.foo
-        one/b.foo
-        one/two/C.Foo2
-        one/two/c.foo",
+        "./a.foo
+        ./one/b.foo
+        ./one/two/C.Foo2
+        ./one/two/c.foo",
     );
 }
 
@@ -317,19 +317,19 @@ fn test_full_path_glob_searches() {
 
     te.assert_output(
         &["--glob", "--full-path", "**/one/**/*.foo"],
-        "one/b.foo
-        one/two/c.foo
-        one/two/three/d.foo",
+        "./one/b.foo
+        ./one/two/c.foo
+        ./one/two/three/d.foo",
     );
 
     te.assert_output(
         &["--glob", "--full-path", "**/one/*/*.foo"],
-        " one/two/c.foo",
+        " ./one/two/c.foo",
     );
 
     te.assert_output(
         &["--glob", "--full-path", "**/one/*/*/*.foo"],
-        " one/two/three/d.foo",
+        " ./one/two/three/d.foo",
     );
 }
 
@@ -339,11 +339,11 @@ fn test_smart_case_glob_searches() {
 
     te.assert_output(
         &["--glob", "c.foo*"],
-        "one/two/C.Foo2
-        one/two/c.foo",
+        "./one/two/C.Foo2
+        ./one/two/c.foo",
     );
 
-    te.assert_output(&["--glob", "C.Foo*"], "one/two/C.Foo2");
+    te.assert_output(&["--glob", "C.Foo*"], "./one/two/C.Foo2");
 }
 
 /// Glob-based searches (--glob) in combination with --case-sensitive
@@ -351,7 +351,7 @@ fn test_smart_case_glob_searches() {
 fn test_case_sensitive_glob_searches() {
     let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);
 
-    te.assert_output(&["--glob", "--case-sensitive", "c.foo*"], "one/two/c.foo");
+    te.assert_output(&["--glob", "--case-sensitive", "c.foo*"], "./one/two/c.foo");
 }
 
 /// Glob-based searches (--glob) in combination with --extension
@@ -361,7 +361,7 @@ fn test_glob_searches_with_extension() {
 
     te.assert_output(
         &["--glob", "--extension", "foo2", "[a-z].*"],
-        "one/two/C.Foo2",
+        "./one/two/C.Foo2",
     );
 }
 
@@ -370,7 +370,7 @@ fn test_glob_searches_with_extension() {
 fn test_regex_overrides_glob() {
     let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);
 
-    te.assert_output(&["--glob", "--regex", "Foo2$"], "one/two/C.Foo2");
+    te.assert_output(&["--glob", "--regex", "Foo2$"], "./one/two/C.Foo2");
 }
 
 /// Full path search (--full-path)
@@ -386,8 +386,8 @@ fn test_full_path() {
             "--full-path",
             &format!("^{prefix}.*three.*foo$", prefix = prefix),
         ],
-        "one/two/three/d.foo
-        one/two/three/directory_foo",
+        "./one/two/three/d.foo
+        ./one/two/three/directory_foo",
     );
 }
 
@@ -398,13 +398,13 @@ fn test_hidden() {
 
     te.assert_output(
         &["--hidden", "foo"],
-        ".hidden.foo
-        a.foo
-        one/b.foo
-        one/two/c.foo
-        one/two/C.Foo2
-        one/two/three/d.foo
-        one/two/three/directory_foo",
+        "./.hidden.foo
+        ./a.foo
+        ./one/b.foo
+        ./one/two/c.foo
+        ./one/two/C.Foo2
+        ./one/two/three/d.foo
+        ./one/two/three/directory_foo",
     );
 }
 
@@ -426,7 +426,7 @@ fn test_hidden_file_attribute() {
         .open(te.test_root().join("hidden-file.txt"))
         .unwrap();
 
-    te.assert_output(&["--hidden", "hidden-file.txt"], "hidden-file.txt");
+    te.assert_output(&["--hidden", "hidden-file.txt"], "./hidden-file.txt");
     te.assert_output(&["hidden-file.txt"], "");
 }
 
@@ -437,27 +437,27 @@ fn test_no_ignore() {
 
     te.assert_output(
         &["--no-ignore", "foo"],
-        "a.foo
-        fdignored.foo
-        gitignored.foo
-        one/b.foo
-        one/two/c.foo
-        one/two/C.Foo2
-        one/two/three/d.foo
-        one/two/three/directory_foo",
+        "./a.foo
+        ./fdignored.foo
+        ./gitignored.foo
+        ./one/b.foo
+        ./one/two/c.foo
+        ./one/two/C.Foo2
+        ./one/two/three/d.foo
+        ./one/two/three/directory_foo",
     );
 
     te.assert_output(
         &["--hidden", "--no-ignore", "foo"],
-        ".hidden.foo
-        a.foo
-        fdignored.foo
-        gitignored.foo
-        one/b.foo
-        one/two/c.foo
-        one/two/C.Foo2
-        one/two/three/d.foo
-        one/two/three/directory_foo",
+        "./.hidden.foo
+        ./a.foo
+        ./fdignored.foo
+        ./gitignored.foo
+        ./one/b.foo
+        ./one/two/c.foo
+        ./one/two/C.Foo2
+        ./one/two/three/d.foo
+        ./one/two/three/directory_foo",
     );
 }
 
@@ -482,20 +482,20 @@ fn test_gitignore_and_fdignore() {
         .write_all(b"ignored-by-gitignore\nignored-by-both")
         .unwrap();
 
-    te.assert_output(&["ignored"], "ignored-by-nothing");
+    te.assert_output(&["ignored"], "./ignored-by-nothing");
 
     te.assert_output(
         &["--no-ignore-vcs", "ignored"],
-        "ignored-by-nothing
-        ignored-by-gitignore",
+        "./ignored-by-nothing
+        ./ignored-by-gitignore",
     );
 
     te.assert_output(
         &["--no-ignore", "ignored"],
-        "ignored-by-nothing
-        ignored-by-fdignore
-        ignored-by-gitignore
-        ignored-by-both",
+        "./ignored-by-nothing
+        ./ignored-by-fdignore
+        ./ignored-by-gitignore
+        ./ignored-by-both",
     );
 }
 
@@ -521,13 +521,13 @@ fn test_no_ignore_parent() {
         .write_all(b"child-ignored")
         .unwrap();
 
-    te.assert_output_subdirectory("inner", &[], "not-ignored");
+    te.assert_output_subdirectory("inner", &[], "./not-ignored");
 
     te.assert_output_subdirectory(
         "inner",
         &["--no-ignore-parent"],
-        "parent-ignored
-        not-ignored",
+        "./parent-ignored
+        ./not-ignored",
     );
 }
 
@@ -559,15 +559,15 @@ fn test_no_ignore_parent_inner_git() {
     te.assert_output_subdirectory(
         "inner",
         &[],
-        "not-ignored
-        parent-ignored",
+        "./not-ignored
+        ./parent-ignored",
     );
 
     te.assert_output_subdirectory(
         "inner",
         &["--no-ignore-parent"],
-        "not-ignored
-        parent-ignored",
+        "./not-ignored
+        ./parent-ignored",
     );
 }
 
@@ -590,11 +590,11 @@ fn test_custom_ignore_precedence() {
         .write_all(b"!foo")
         .unwrap();
 
-    te.assert_output(&["foo"], "inner/foo");
+    te.assert_output(&["foo"], "./inner/foo");
 
-    te.assert_output(&["--no-ignore-vcs", "foo"], "inner/foo");
+    te.assert_output(&["--no-ignore-vcs", "foo"], "./inner/foo");
 
-    te.assert_output(&["--no-ignore", "foo"], "inner/foo");
+    te.assert_output(&["--no-ignore", "foo"], "./inner/foo");
 }
 
 /// VCS ignored files (--no-ignore-vcs)
@@ -604,13 +604,13 @@ fn test_no_ignore_vcs() {
 
     te.assert_output(
         &["--no-ignore-vcs", "foo"],
-        "a.foo
-        gitignored.foo
-        one/b.foo
-        one/two/c.foo
-        one/two/C.Foo2
-        one/two/three/d.foo
-        one/two/three/directory_foo",
+        "./a.foo
+        ./gitignored.foo
+        ./one/b.foo
+        ./one/two/c.foo
+        ./one/two/C.Foo2
+        ./one/two/three/d.foo
+        ./one/two/three/directory_foo",
     );
 }
 
@@ -627,9 +627,9 @@ fn test_custom_ignore_files() {
 
     te.assert_output(
         &["--ignore-file", "custom.ignore", "foo"],
-        "a.foo
-        one/b.foo
-        one/two/c.foo",
+        "./a.foo
+        ./one/b.foo
+        ./one/two/c.foo",
     );
 }
 
@@ -640,27 +640,27 @@ fn test_no_ignore_aliases() {
 
     te.assert_output(
         &["-u", "foo"],
-        "a.foo
-        fdignored.foo
-        gitignored.foo
-        one/b.foo
-        one/two/c.foo
-        one/two/C.Foo2
-        one/two/three/d.foo
-        one/two/three/directory_foo",
+        "./a.foo
+        ./fdignored.foo
+        ./gitignored.foo
+        ./one/b.foo
+        ./one/two/c.foo
+        ./one/two/C.Foo2
+        ./one/two/three/d.foo
+        ./one/two/three/directory_foo",
     );
 
     te.assert_output(
         &["-uu", "foo"],
-        ".hidden.foo
-        a.foo
-        fdignored.foo
-        gitignored.foo
-        one/b.foo
-        one/two/c.foo
-        one/two/C.Foo2
-        one/two/three/d.foo
-        one/two/three/directory_foo",
+        "./.hidden.foo
+        ./a.foo
+        ./fdignored.foo
+        ./gitignored.foo
+        ./one/b.foo
+        ./one/two/c.foo
+        ./one/two/C.Foo2
+        ./one/two/three/d.foo
+        ./one/two/three/directory_foo",
     );
 }
 
@@ -671,10 +671,10 @@ fn test_follow() {
 
     te.assert_output(
         &["--follow", "c.foo"],
-        "one/two/c.foo
-        one/two/C.Foo2
-        symlink/c.foo
-        symlink/C.Foo2",
+        "./one/two/c.foo
+        ./one/two/C.Foo2
+        ./symlink/c.foo
+        ./symlink/C.Foo2",
     );
 }
 
@@ -729,20 +729,20 @@ fn test_follow_broken_symlink() {
 
     te.assert_output(
         &["symlink"],
-        "broken_symlink
-        symlink",
+        "./broken_symlink
+        ./symlink",
     );
     te.assert_output(
         &["--type", "symlink", "symlink"],
-        "broken_symlink
-        symlink",
+        "./broken_symlink
+        ./symlink",
     );
 
     te.assert_output(&["--type", "file", "symlink"], "");
 
     te.assert_output(
         &["--follow", "--type", "symlink", "symlink"],
-        "broken_symlink",
+        "./broken_symlink",
     );
     te.assert_output(&["--follow", "--type", "file", "symlink"], "");
 }
@@ -754,12 +754,12 @@ fn test_print0() {
 
     te.assert_output(
         &["--print0", "foo"],
-        "a.fooNULL
-        one/b.fooNULL
-        one/two/C.Foo2NULL
-        one/two/c.fooNULL
-        one/two/three/d.fooNULL
-        one/two/three/directory_fooNULL",
+        "./a.fooNULL
+        ./one/b.fooNULL
+        ./one/two/C.Foo2NULL
+        ./one/two/c.fooNULL
+        ./one/two/three/d.fooNULL
+        ./one/two/three/directory_fooNULL",
     );
 }
 
@@ -770,33 +770,33 @@ fn test_max_depth() {
 
     te.assert_output(
         &["--max-depth", "3"],
-        "a.foo
-        e1 e2
-        one
-        one/b.foo
-        one/two
-        one/two/c.foo
-        one/two/C.Foo2
-        one/two/three
-        symlink",
+        "./a.foo
+        ./e1 e2
+        ./one
+        ./one/b.foo
+        ./one/two
+        ./one/two/c.foo
+        ./one/two/C.Foo2
+        ./one/two/three
+        ./symlink",
     );
 
     te.assert_output(
         &["--max-depth", "2"],
-        "a.foo
-        e1 e2
-        one
-        one/b.foo
-        one/two
-        symlink",
+        "./a.foo
+        ./e1 e2
+        ./one
+        ./one/b.foo
+        ./one/two
+        ./symlink",
     );
 
     te.assert_output(
         &["--max-depth", "1"],
-        "a.foo
-        e1 e2
-        one
-        symlink",
+        "./a.foo
+        ./e1 e2
+        ./one
+        ./symlink",
     );
 }
 
@@ -807,17 +807,17 @@ fn test_min_depth() {
 
     te.assert_output(
         &["--min-depth", "3"],
-        "one/two/c.foo
-        one/two/C.Foo2
-        one/two/three
-        one/two/three/d.foo
-        one/two/three/directory_foo",
+        "./one/two/c.foo
+        ./one/two/C.Foo2
+        ./one/two/three
+        ./one/two/three/d.foo
+        ./one/two/three/directory_foo",
     );
 
     te.assert_output(
         &["--min-depth", "4"],
-        "one/two/three/d.foo
-        one/two/three/directory_foo",
+        "./one/two/three/d.foo
+        ./one/two/three/directory_foo",
     );
 }
 
@@ -828,9 +828,9 @@ fn test_exact_depth() {
 
     te.assert_output(
         &["--exact-depth", "3"],
-        "one/two/c.foo
-        one/two/C.Foo2
-        one/two/three",
+        "./one/two/c.foo
+        ./one/two/C.Foo2
+        ./one/two/three",
     );
 }
 
@@ -839,32 +839,32 @@ fn test_exact_depth() {
 fn test_prune() {
     let dirs = &["foo/bar", "bar/foo", "baz"];
     let files = &[
-        "foo/foo.file",
-        "foo/bar/foo.file",
-        "bar/foo.file",
-        "bar/foo/foo.file",
-        "baz/foo.file",
+        "./foo/foo.file",
+        "./foo/bar/foo.file",
+        "./bar/foo.file",
+        "./bar/foo/foo.file",
+        "./baz/foo.file",
     ];
 
     let te = TestEnv::new(dirs, files);
 
     te.assert_output(
         &["foo"],
-        "foo
-        foo/foo.file
-        foo/bar/foo.file
-        bar/foo.file
-        bar/foo
-        bar/foo/foo.file
-        baz/foo.file",
+        "./foo
+        ./foo/foo.file
+        ./foo/bar/foo.file
+        ./bar/foo.file
+        ./bar/foo
+        ./bar/foo/foo.file
+        ./baz/foo.file",
     );
 
     te.assert_output(
         &["--prune", "foo"],
-        "foo
-        bar/foo
-        bar/foo.file
-        baz/foo.file",
+        "./foo
+        ./bar/foo
+        ./bar/foo.file
+        ./baz/foo.file",
     );
 }
 
@@ -951,34 +951,34 @@ fn test_type() {
 
     te.assert_output(
         &["--type", "f"],
-        "a.foo
-        e1 e2
-        one/b.foo
-        one/two/c.foo
-        one/two/C.Foo2
-        one/two/three/d.foo",
+        "./a.foo
+        ./e1 e2
+        ./one/b.foo
+        ./one/two/c.foo
+        ./one/two/C.Foo2
+        ./one/two/three/d.foo",
     );
 
-    te.assert_output(&["--type", "f", "e1"], "e1 e2");
+    te.assert_output(&["--type", "f", "e1"], "./e1 e2");
 
     te.assert_output(
         &["--type", "d"],
-        "one
-        one/two
-        one/two/three
-        one/two/three/directory_foo",
+        "./one
+        ./one/two
+        ./one/two/three
+        ./one/two/three/directory_foo",
     );
 
     te.assert_output(
         &["--type", "d", "--type", "l"],
-        "one
-        one/two
-        one/two/three
-        one/two/three/directory_foo
-        symlink",
+        "./one
+        ./one/two
+        ./one/two/three
+        ./one/two/three/directory_foo
+        ./symlink",
     );
 
-    te.assert_output(&["--type", "l"], "symlink");
+    te.assert_output(&["--type", "l"], "./symlink");
 }
 
 /// Test `--type executable`
@@ -996,15 +996,15 @@ fn test_type_executable() {
         .open(te.test_root().join("executable-file.sh"))
         .unwrap();
 
-    te.assert_output(&["--type", "executable"], "executable-file.sh");
+    te.assert_output(&["--type", "executable"], "./executable-file.sh");
 
     te.assert_output(
         &["--type", "executable", "--type", "directory"],
-        "executable-file.sh
-        one
-        one/two
-        one/two/three
-        one/two/three/directory_foo",
+        "./executable-file.sh
+        ./one
+        ./one/two
+        ./one/two/three
+        ./one/two/three/directory_foo",
     );
 }
 
@@ -1020,19 +1020,19 @@ fn test_type_empty() {
 
     te.assert_output(
         &["--type", "empty"],
-        "0_bytes.foo
-        dir_empty",
+        "./0_bytes.foo
+        ./dir_empty",
     );
 
     te.assert_output(
         &["--type", "empty", "--type", "file", "--type", "directory"],
-        "0_bytes.foo
-        dir_empty",
+        "./0_bytes.foo
+        ./dir_empty",
     );
 
-    te.assert_output(&["--type", "empty", "--type", "file"], "0_bytes.foo");
+    te.assert_output(&["--type", "empty", "--type", "file"], "./0_bytes.foo");
 
-    te.assert_output(&["--type", "empty", "--type", "directory"], "dir_empty");
+    te.assert_output(&["--type", "empty", "--type", "directory"], "./dir_empty");
 }
 
 /// File extension (--extension)
@@ -1042,54 +1042,54 @@ fn test_extension() {
 
     te.assert_output(
         &["--extension", "foo"],
-        "a.foo
-        one/b.foo
-        one/two/c.foo
-        one/two/three/d.foo",
+        "./a.foo
+        ./one/b.foo
+        ./one/two/c.foo
+        ./one/two/three/d.foo",
     );
 
     te.assert_output(
         &["--extension", ".foo"],
-        "a.foo
-        one/b.foo
-        one/two/c.foo
-        one/two/three/d.foo",
+        "./a.foo
+        ./one/b.foo
+        ./one/two/c.foo
+        ./one/two/three/d.foo",
     );
 
     te.assert_output(
         &["--extension", ".foo", "--extension", "foo2"],
-        "a.foo
-        one/b.foo
-        one/two/c.foo
-        one/two/three/d.foo
-        one/two/C.Foo2",
+        "./a.foo
+        ./one/b.foo
+        ./one/two/c.foo
+        ./one/two/three/d.foo
+        ./one/two/C.Foo2",
     );
 
-    te.assert_output(&["--extension", ".foo", "a"], "a.foo");
+    te.assert_output(&["--extension", ".foo", "a"], "./a.foo");
 
-    te.assert_output(&["--extension", "foo2"], "one/two/C.Foo2");
+    te.assert_output(&["--extension", "foo2"], "./one/two/C.Foo2");
 
     let te2 = TestEnv::new(&[], &["spam.bar.baz", "egg.bar.baz", "yolk.bar.baz.sig"]);
 
     te2.assert_output(
         &["--extension", ".bar.baz"],
-        "spam.bar.baz
-        egg.bar.baz",
+        "./spam.bar.baz
+        ./egg.bar.baz",
     );
 
-    te2.assert_output(&["--extension", "sig"], "yolk.bar.baz.sig");
+    te2.assert_output(&["--extension", "sig"], "./yolk.bar.baz.sig");
 
-    te2.assert_output(&["--extension", "bar.baz.sig"], "yolk.bar.baz.sig");
+    te2.assert_output(&["--extension", "bar.baz.sig"], "./yolk.bar.baz.sig");
 
     let te3 = TestEnv::new(&[], &["latin1.e\u{301}xt", "smiley.☻"]);
 
-    te3.assert_output(&["--extension", "☻"], "smiley.☻");
+    te3.assert_output(&["--extension", "☻"], "./smiley.☻");
 
-    te3.assert_output(&["--extension", ".e\u{301}xt"], "latin1.e\u{301}xt");
+    te3.assert_output(&["--extension", ".e\u{301}xt"], "./latin1.e\u{301}xt");
 
     let te4 = TestEnv::new(&[], &[".hidden", "test.hidden"]);
 
-    te4.assert_output(&["--hidden", "--extension", ".hidden"], "test.hidden");
+    te4.assert_output(&["--hidden", "--extension", ".hidden"], "./test.hidden");
 }
 
 /// No file extension (test for the pattern provided in the --help text)
@@ -1102,21 +1102,21 @@ fn test_no_extension() {
 
     te.assert_output(
         &["^[^.]+$"],
-        "aa
-        one
-        one/bb
-        one/two
-        one/two/three
-        one/two/three/d
-        one/two/three/directory_foo
-        symlink",
+        "./aa
+        ./one
+        ./one/bb
+        ./one/two
+        ./one/two/three
+        ./one/two/three/d
+        ./one/two/three/directory_foo
+        ./symlink",
     );
 
     te.assert_output(
         &["^[^.]+$", "--type", "file"],
-        "aa
-        one/bb
-        one/two/three/d",
+        "./aa
+        ./one/bb
+        ./one/two/three/d",
     );
 }
 
@@ -1251,46 +1251,46 @@ fn test_excludes() {
 
     te.assert_output(
         &["--exclude", "*.foo"],
-        "one
-        one/two
-        one/two/C.Foo2
-        one/two/three
-        one/two/three/directory_foo
-        e1 e2
-        symlink",
+        "./one
+        ./one/two
+        ./one/two/C.Foo2
+        ./one/two/three
+        ./one/two/three/directory_foo
+        ./e1 e2
+        ./symlink",
     );
 
     te.assert_output(
         &["--exclude", "*.foo", "--exclude", "*.Foo2"],
-        "one
-        one/two
-        one/two/three
-        one/two/three/directory_foo
-        e1 e2
-        symlink",
+        "./one
+        ./one/two
+        ./one/two/three
+        ./one/two/three/directory_foo
+        ./e1 e2
+        ./symlink",
     );
 
     te.assert_output(
         &["--exclude", "*.foo", "--exclude", "*.Foo2", "foo"],
-        "one/two/three/directory_foo",
+        "./one/two/three/directory_foo",
     );
 
     te.assert_output(
         &["--exclude", "one/two", "foo"],
-        "a.foo
-        one/b.foo",
+        "./a.foo
+        ./one/b.foo",
     );
 
     te.assert_output(
         &["--exclude", "one/**/*.foo"],
-        "a.foo
-        e1 e2
-        one
-        one/two
-        one/two/C.Foo2
-        one/two/three
-        one/two/three/directory_foo
-        symlink",
+        "./a.foo
+        ./e1 e2
+        ./one
+        ./one/two
+        ./one/two/C.Foo2
+        ./one/two/three
+        ./one/two/three/directory_foo
+        ./symlink",
     );
 }
 
@@ -1315,12 +1315,12 @@ fn test_exec() {
 
         te.assert_output(
             &["foo", "--exec", "echo", "{}"],
-            "a.foo
-            one/b.foo
-            one/two/C.Foo2
-            one/two/c.foo
-            one/two/three/d.foo
-            one/two/three/directory_foo",
+            "./a.foo
+            ./one/b.foo
+            ./one/two/C.Foo2
+            ./one/two/c.foo
+            ./one/two/three/d.foo
+            ./one/two/three/directory_foo",
         );
 
         te.assert_output(
@@ -1356,14 +1356,14 @@ fn test_exec() {
         te.assert_output(
             &["foo", "--exec", "echo", "{//}"],
             ".
-            one
-            one/two
-            one/two
-            one/two/three
-            one/two/three",
+            ./one
+            ./one/two
+            ./one/two
+            ./one/two/three
+            ./one/two/three",
         );
 
-        te.assert_output(&["e1", "--exec", "printf", "%s.%s\n"], "e1 e2.");
+        te.assert_output(&["e1", "--exec", "printf", "%s.%s\n"], "./e1 e2.");
     }
 }
 
@@ -1384,7 +1384,7 @@ fn test_exec_batch() {
 
         te.assert_output(
             &["foo", "--exec-batch", "echo", "{}"],
-            "a.foo one/b.foo one/two/C.Foo2 one/two/c.foo one/two/three/d.foo one/two/three/directory_foo",
+            "./a.foo ./one/b.foo ./one/two/C.Foo2 ./one/two/c.foo ./one/two/three/d.foo ./one/two/three/directory_foo",
         );
 
         te.assert_output(
@@ -1430,7 +1430,7 @@ fn test_exec_batch_with_limit() {
 
     te.assert_output(
         &["foo", "--batch-size", "0", "--exec-batch", "echo", "{}"],
-        "a.foo one/b.foo one/two/C.Foo2 one/two/c.foo one/two/three/d.foo one/two/three/directory_foo",
+        "./a.foo ./one/b.foo ./one/two/C.Foo2 ./one/two/c.foo ./one/two/three/d.foo ./one/two/three/directory_foo",
     );
 
     let output = te.assert_success_and_get_output(
@@ -1451,12 +1451,12 @@ fn test_exec_batch_with_limit() {
     assert_eq!(
         &paths,
         &[
-            "a.foo",
-            "one/b.foo",
-            "one/two/C.Foo2",
-            "one/two/c.foo",
-            "one/two/three/d.foo",
-            "one/two/three/directory_foo"
+            "./a.foo",
+            "./one/b.foo",
+            "./one/two/C.Foo2",
+            "./one/two/c.foo",
+            "./one/two/three/d.foo",
+            "./one/two/three/directory_foo"
         ],
     );
 }
@@ -1486,12 +1486,12 @@ fn test_exec_with_separator() {
 
     te.assert_output(
         &["--path-separator=#", "foo", "--exec", "echo", "{}"],
-        "a.foo
-            one#b.foo
-            one#two#C.Foo2
-            one#two#c.foo
-            one#two#three#d.foo
-            one#two#three#directory_foo",
+        ".#a.foo
+            .#one#b.foo
+            .#one#two#C.Foo2
+            .#one#two#c.foo
+            .#one#two#three#d.foo
+            .#one#two#three#directory_foo",
     );
 
     te.assert_output(
@@ -1527,16 +1527,16 @@ fn test_exec_with_separator() {
     te.assert_output(
         &["--path-separator=#", "foo", "--exec", "echo", "{//}"],
         ".
-            one
-            one#two
-            one#two
-            one#two#three
-            one#two#three",
+            .#one
+            .#one#two
+            .#one#two
+            .#one#two#three
+            .#one#two#three",
     );
 
     te.assert_output(
         &["--path-separator=#", "e1", "--exec", "printf", "%s.%s\n"],
-        "e1 e2.",
+        ".#e1 e2.",
     );
 }
 
@@ -1563,12 +1563,12 @@ fn test_fixed_strings() {
     // Regex search, dot is treated as "any character"
     te.assert_output(
         &["a.foo"],
-        "test1/a.foo
-         test1/a_foo",
+        "./test1/a.foo
+         ./test1/a_foo",
     );
 
     // Literal search, dot is treated as character
-    te.assert_output(&["--fixed-strings", "a.foo"], "test1/a.foo");
+    te.assert_output(&["--fixed-strings", "a.foo"], "./test1/a.foo");
 
     // Regex search, parens are treated as group
     te.assert_output(&["download (1)"], "");
@@ -1576,7 +1576,7 @@ fn test_fixed_strings() {
     // Literal search, parens are treated as characters
     te.assert_output(
         &["--fixed-strings", "download (1)"],
-        "test2/Download (1).tar.gz",
+        "./test2/Download (1).tar.gz",
     );
 
     // Combine with --case-sensitive
@@ -1622,69 +1622,81 @@ fn test_size() {
     // Zero and non-zero sized files.
     te.assert_output(
         &["", "--size", "+0B"],
-        "0_bytes.foo
-        11_bytes.foo
-        30_bytes.foo
-        3_kilobytes.foo
-        4_kibibytes.foo",
+        "./0_bytes.foo
+        ./11_bytes.foo
+        ./30_bytes.foo
+        ./3_kilobytes.foo
+        ./4_kibibytes.foo",
     );
 
     // Zero sized files.
-    te.assert_output(&["", "--size", "-0B"], "0_bytes.foo");
-    te.assert_output(&["", "--size", "0B"], "0_bytes.foo");
-    te.assert_output(&["", "--size=0B"], "0_bytes.foo");
-    te.assert_output(&["", "-S", "0B"], "0_bytes.foo");
+    te.assert_output(&["", "--size", "-0B"], "./0_bytes.foo");
+    te.assert_output(&["", "--size", "0B"], "./0_bytes.foo");
+    te.assert_output(&["", "--size=0B"], "./0_bytes.foo");
+    te.assert_output(&["", "-S", "0B"], "./0_bytes.foo");
 
     // Files with 2 bytes or more.
     te.assert_output(
         &["", "--size", "+2B"],
-        "11_bytes.foo
-        30_bytes.foo
-        3_kilobytes.foo
-        4_kibibytes.foo",
+        "./11_bytes.foo
+        ./30_bytes.foo
+        ./3_kilobytes.foo
+        ./4_kibibytes.foo",
     );
 
     // Files with 2 bytes or less.
-    te.assert_output(&["", "--size", "-2B"], "0_bytes.foo");
+    te.assert_output(&["", "--size", "-2B"], "./0_bytes.foo");
 
     // Files with size between 1 byte and 11 bytes.
-    te.assert_output(&["", "--size", "+1B", "--size", "-11B"], "11_bytes.foo");
+    te.assert_output(&["", "--size", "+1B", "--size", "-11B"], "./11_bytes.foo");
 
     // Files with size equal 11 bytes.
-    te.assert_output(&["", "--size", "11B"], "11_bytes.foo");
+    te.assert_output(&["", "--size", "11B"], "./11_bytes.foo");
 
     // Files with size between 1 byte and 30 bytes.
     te.assert_output(
         &["", "--size", "+1B", "--size", "-30B"],
-        "11_bytes.foo
-        30_bytes.foo",
+        "./11_bytes.foo
+        ./30_bytes.foo",
     );
 
     // Combine with a search pattern
-    te.assert_output(&["^11_", "--size", "+1B", "--size", "-30B"], "11_bytes.foo");
+    te.assert_output(
+        &["^11_", "--size", "+1B", "--size", "-30B"],
+        "./11_bytes.foo",
+    );
 
     // Files with size between 12 and 30 bytes.
-    te.assert_output(&["", "--size", "+12B", "--size", "-30B"], "30_bytes.foo");
+    te.assert_output(&["", "--size", "+12B", "--size", "-30B"], "./30_bytes.foo");
 
     // Files with size between 31 and 100 bytes.
     te.assert_output(&["", "--size", "+31B", "--size", "-100B"], "");
 
     // Files with size between 3 kibibytes and 5 kibibytes.
-    te.assert_output(&["", "--size", "+3ki", "--size", "-5ki"], "4_kibibytes.foo");
+    te.assert_output(
+        &["", "--size", "+3ki", "--size", "-5ki"],
+        "./4_kibibytes.foo",
+    );
 
     // Files with size between 3 kilobytes and 5 kilobytes.
     te.assert_output(
         &["", "--size", "+3k", "--size", "-5k"],
-        "3_kilobytes.foo
-        4_kibibytes.foo",
+        "./3_kilobytes.foo
+        ./4_kibibytes.foo",
     );
 
     // Files with size greater than 3 kilobytes and less than 3 kibibytes.
-    te.assert_output(&["", "--size", "+3k", "--size", "-3ki"], "3_kilobytes.foo");
+    te.assert_output(
+        &["", "--size", "+3k", "--size", "-3ki"],
+        "./3_kilobytes.foo",
+    );
 
     // Files with size equal 4 kibibytes.
-    te.assert_output(&["", "--size", "+4ki", "--size", "-4ki"], "4_kibibytes.foo");
-    te.assert_output(&["", "--size", "4ki"], "4_kibibytes.foo");
+    te.assert_output(
+        &["", "--size", "+4ki", "--size", "-4ki"],
+        "./4_kibibytes.foo",
+    );
+    te.assert_output(&["", "--size", "4ki"], "./4_kibibytes.foo");
 }
 
 #[cfg(test)]
@@ -1720,23 +1732,23 @@ fn test_modified_relative() {
 
     te.assert_output(
         &["", "--changed-within", "15min"],
-        "foo_0_now
-        bar_1_min
-        foo_10_min",
+        "./foo_0_now
+        ./bar_1_min
+        ./foo_10_min",
     );
 
     te.assert_output(
         &["", "--change-older-than", "15min"],
-        "bar_1_h
-        foo_2_h
-        bar_1_day",
+        "./bar_1_h
+        ./foo_2_h
+        ./bar_1_day",
     );
 
     te.assert_output(
         &["foo", "--changed-within", "12h"],
-        "foo_0_now
-        foo_10_min
-        foo_2_h",
+        "./foo_0_now
+        ./foo_10_min
+        ./foo_2_h",
     );
 }
 
@@ -1756,11 +1768,11 @@ fn test_modified_absolute() {
 
     te.assert_output(
         &["", "--change-newer-than", "2018-01-01 00:00:00"],
-        "15mar2018",
+        "./15mar2018",
     );
     te.assert_output(
         &["", "--changed-before", "2018-01-01 00:00:00"],
-        "30dec2017",
+        "./30dec2017",
     );
 }
 
@@ -1784,21 +1796,21 @@ fn test_base_directory() {
 
     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",
+        "./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",
+        "./c.foo
+        ./C.Foo2
+        ./three/d.foo
+        ./three/directory_foo",
     );
 
     // Explicit root path
@@ -1834,15 +1846,15 @@ fn test_max_results() {
     // Unrestricted
     te.assert_output(
         &["--max-results=0", "c.foo"],
-        "one/two/C.Foo2
-         one/two/c.foo",
+        "./one/two/C.Foo2
+         ./one/two/c.foo",
     );
 
     // Limited to two results
     te.assert_output(
         &["--max-results=2", "c.foo"],
-        "one/two/C.Foo2
-         one/two/c.foo",
+        "./one/two/C.Foo2
+         ./one/two/c.foo",
     );
 
     // Limited to one result. We could find either C.Foo2 or c.foo
@@ -1851,7 +1863,7 @@ fn test_max_results() {
         let stdout = String::from_utf8_lossy(&output.stdout)
             .trim()
             .replace(&std::path::MAIN_SEPARATOR.to_string(), "/");
-        assert!(stdout == "one/two/C.Foo2" || stdout == "one/two/c.foo");
+        assert!(stdout == "./one/two/C.Foo2" || stdout == "./one/two/c.foo");
     };
     assert_just_one_result_with_option("--max-results=1");
     assert_just_one_result_with_option("-1");
@@ -1964,7 +1976,27 @@ fn test_error_if_hidden_not_set_and_pattern_starts_with_dot() {
     te.assert_failure(&["^\\.gitignore"]);
     te.assert_failure(&["--glob", ".gitignore"]);
 
-    te.assert_output(&["--hidden", "^\\.gitignore"], ".gitignore");
-    te.assert_output(&["--hidden", "--glob", ".gitignore"], ".gitignore");
+    te.assert_output(&["--hidden", "^\\.gitignore"], "./.gitignore");
+    te.assert_output(&["--hidden", "--glob", ".gitignore"], "./.gitignore");
     te.assert_output(&[".gitignore"], "");
 }
+
+#[test]
+fn test_strip_cwd_prefix() {
+    let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);
+
+    te.assert_output(
+        &["--strip-cwd-prefix", "."],
+        "a.foo
+        e1 e2
+        one
+        one/b.foo
+        one/two
+        one/two/c.foo
+        one/two/C.Foo2
+        one/two/three
+        one/two/three/d.foo
+        one/two/three/directory_foo
+        symlink",
+    );
+}