diff --git a/src/builtins/path.cpp b/src/builtins/path.cpp index b1840d9fd..fca03bd82 100644 --- a/src/builtins/path.cpp +++ b/src/builtins/path.cpp @@ -675,6 +675,11 @@ static int path_resolve(parser_t &parser, io_streams_t &streams, int argc, const } } + // Normalize the path so "../" components are eliminated even after + // nonexistent or non-directory components. + // Otherwise `path resolve foo/../` will be `$PWD/foo/../` if foo is a file. + real = normalize_path(*real, false); + // Return 0 if we found a realpath. if (opts.quiet) { return STATUS_CMD_OK; diff --git a/tests/checks/path.fish b/tests/checks/path.fish index ae14e5022..7334f0e7d 100644 --- a/tests/checks/path.fish +++ b/tests/checks/path.fish @@ -118,6 +118,10 @@ path resolve bin//sh | string match -r -- 'bin/bash$' # sh here is bash # CHECK: bin/bash +# "../" cancels out even files. +path resolve bin//sh/../ | string match -r -- 'bin$' +# CHECK: bin + # `path resolve` with nonexistent paths set -l path (path resolve foo/bar) string match -rq "^"(pwd -P | string escape --style=regex)'/' -- $path