How can I find the first missing directory in a long path?
One of my favourite utilties is namei
, part of util-linux
and hence generally present only on Linux:
$ namei /usr/share/foo/bar
f: /usr/share/foo/bar
d /
d usr
d share
foo - No such file or directory
But its output is not very parseable. So, if you just wish to point out something is missing, namei
might be useful.
It's useful for troubleshooting general problems in accessing a path, since you can get it to state whether a component is a link or a mount point, as well as its permissions:
$ ln -sf /usr/foo/bar /tmp/
$ namei -lx /tmp/bar
f: /tmp/bar
Drwxr-xr-x root root /
Drwxrwxrwt root root tmp
lrwxrwxrwx muru muru bar -> /usr/foo/bar
Drwxr-xr-x root root /
drwxr-xr-x root root usr
foo - No such file or directory
The capital D
indicates a mount point.
Given a canonical pathname, such as yours, this will work:
set -f --; IFS=/
for p in $pathname
do [ -e "$*/$p" ] || break
set -- "$@" "$p"
done; printf %s\\n "$*"
That prints through the last fully existing/accessible component of $pathname
, and puts each of those separately into the arg array. The first nonexistent component is not printed, but it is saved in $p
.
You might approach it oppositely:
until cd -- "$path" && cd -
do case $path in
(*[!/]/*)
path="${path%/*}"
;; (*) ! break
esac
done 2>/dev/null && cd -
That will either return appropriately or will pare down $path
as needed. It declines to attempt a change to /
, but if successful will print both your current working directory and the directory to which it changes to stdout. Your current $PWD
will be put in $OLDPWD
as well.