如何找到长路径中第一个丢失的目录?

如何找到长路径中第一个丢失的目录?

想象一下我有一条不存在的路径:

$ ls /foo/bar/baz/hello/world
ls: cannot access /foo/bar/baz/hello/world: No such file or directory

但我们可以说/foo/bar 存在。有没有一种快速方法可以让我确定这baz是路径中的断点?

我正在使用 Bash。

答案1

我最喜欢的实用程序之一是namei, 部分util-linux因此通常只出现在 Linux 上:

$ namei /usr/share/foo/bar
f: /usr/share/foo/bar
 d /
 d usr
 d share
   foo - No such file or directory

但它的输出不是很容易解析。因此,如果您只是想指出缺少的内容,namei可能会有用。

它对于解决访问路径时的一般问题很有用,因为您可以让它声明组件是链接还是挂载点及其权限:

$ 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

大写字母D表示安装点。

答案2

给定一个规范的路径名,例如您的路径名,这将起作用:

set -f --; IFS=/
for p in $pathname
do    [ -e "$*/$p" ] || break
      set -- "$@" "$p"
done; printf %s\\n "$*"

它会打印 的最后一个完全存在/可访问的组件$pathname,并将每个组件分别放入 arg 数组中。第一个不存在的组件不会被打印,但会保存在$p.

你可能会采取相反的方法:

until cd -- "$path" && cd -
do    case   $path  in
      (*[!/]/*)
              path="${path%/*}"
;;    (*)   ! break
      esac
done  2>/dev/null   && cd -

$path这要么会适当返回,要么会根据需要减少。它拒绝尝试更改/,但如果成功,则会将当前工作目录及其更改到的目录打印到 stdout 。您的电流$PWD也会被输入$OLDPWD

答案3

像这样的东西(考虑带有嵌入空格的路径名):

#!/bin/sh
explain() {
    if [ -d "$1" ]
    then
        printf "\t%s: is a directory\n" "$1"
    elif [ -e "$1" ]
    then
        printf "\t%s: is not a directory\n" "$1"
    else
        printf "\t%s: does not exist\n" "$1"
    fi
}

for item in "$@"
do
    last=
    test="$item"
    printf "testing: '%s'\n" "$item"
    while [ ! -d "$test" ]
    do
        last="$test"
        test=$(dirname "$test")
        [ -z "$test" ] && break
    done
    if [ -n "$last" ]
    then
        explain "$test"
        explain "$last"
    else
        printf "\t%s: ok\n" "$item"
    fi
done

答案4

(( dirct=$(echo ${dir}|tr "/" " "|wc -w)+1 ))
i=2
while [ ${i} -le ${dirct} ]
do
  sdir=$(echo ${dir}|cut -d/ -f1,${i})
  if [ ! -d ${sdir} ]
  then
    echo "Path is broken at ${sdir}"
  fi
  (( i++ ))
done

它并不简单,但如果您要经常使用它,您可以将其放入脚本中,使其可执行并将其粘贴到路径中的某个位置。

买者自负:如果您的任何级别的目录名称包含字符space,则这将不起作用。

相关内容