diff --git a/doc_src/cmds/path.rst b/doc_src/cmds/path.rst index d6d2a0003..1bcc95349 100644 --- a/doc_src/cmds/path.rst +++ b/doc_src/cmds/path.rst @@ -239,6 +239,8 @@ Examples Unlike ``realpath`` or ``path resolve``, it does not make the paths absolute. It also does not resolve any symlinks. As such it can operate on non-existent paths. +Leading "./" components are usually removed. But when a path starts with ``-``, ``path normalize`` will add it instead to avoid confusion with options. + It returns 0 if any normalization was done, i.e. any given path wasn't in canonical form. Examples @@ -257,6 +259,9 @@ Examples >_ path normalize ./my/subdirs/../sub2 my/sub2 + >_ path normalize -- -/foo + ./-/foo + "resolve" subcommand -------------------- diff --git a/src/builtins/path.cpp b/src/builtins/path.cpp index a019d3e23..4ae2c498c 100644 --- a/src/builtins/path.cpp +++ b/src/builtins/path.cpp @@ -482,7 +482,11 @@ static int path_dirname(parser_t &parser, io_streams_t &streams, int argc, const // Not a constref because this must have the same type as wdirname. // cppcheck-suppress passedByValue static wcstring normalize_helper(wcstring path) { - return normalize_path(path, false); + wcstring np = normalize_path(path, false); + if (!np.empty() && np[0] == L'-') { + np = L"./" + np; + } + return np; } static bool filter_path(options_t opts, const wcstring &path) { diff --git a/tests/checks/path.fish b/tests/checks/path.fish index b68b9f87e..ae14e5022 100644 --- a/tests/checks/path.fish +++ b/tests/checks/path.fish @@ -105,6 +105,13 @@ path normalize /bin//bash # The "//" is squashed, but /bin isn't resolved even if your system links it to /usr/bin. # CHECK: /bin/bash +# Paths with "-" get a "./": +path normalize -- -/foo -foo/foo +# CHECK: ./-/foo +# CHECK: ./-foo/foo +path normalize -- ../-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.