diff --git a/doc_src/cmds/path.rst b/doc_src/cmds/path.rst index ccb90504c..c02c45edd 100644 --- a/doc_src/cmds/path.rst +++ b/doc_src/cmds/path.rst @@ -170,6 +170,8 @@ The filter options can either be given as multiple options, or comma-separated - With ``--invert``, the meaning of the filtering is inverted - any path that wouldn't pass (including by not existing) passes, and any path that would pass fails. +When a path starts with ``-``, ``path filter`` will prepend ``./`` to avoid it being interpreted as an option otherwise. + It returns 0 if at least one path passed the filter. ``path is`` is shorthand for ``path filter -q``, i.e. just checking without producing output, see :ref:`The is subcommand `. diff --git a/src/builtins/path.cpp b/src/builtins/path.cpp index b674523f3..a7a912ac2 100644 --- a/src/builtins/path.cpp +++ b/src/builtins/path.cpp @@ -815,7 +815,15 @@ static int path_filter(parser_t &parser, io_streams_t &streams, int argc, const if (ok == opts.invert) continue; } - path_out(streams, opts, *arg); + // We *know* this is a filename, + // and so if it starts with a `-` we *know* it is relative + // to $PWD. So we can add `./`. + if (!arg->empty() && arg->front() == L'-') { + wcstring out = L"./" + *arg; + path_out(streams, opts, out); + } else { + path_out(streams, opts, *arg); + } n_transformed++; if (opts.quiet) return STATUS_CMD_OK; } diff --git a/tests/checks/path.fish b/tests/checks/path.fish index 6f1ce78c2..d9ef9897a 100644 --- a/tests/checks/path.fish +++ b/tests/checks/path.fish @@ -120,6 +120,11 @@ path normalize -- -/foo -foo/foo path normalize -- ../-foo # CHECK: ../-foo +# This goes for filter as well +touch -- -foo +path filter -f -- -foo +# CHECK: ./-foo + # We need to remove the rest of the path because we have no idea what its value looks like. path resolve bin//sh | string match -r -- 'bin/bash$' # The "//" is squashed, and the symlink is resolved.