긴 경로에서 첫 번째 누락 된 디렉토리를 어떻게 찾을 수 있습니까? No such file or

존재하지 않는 경로가 있다고 상상해보십시오.

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

그러나하자 말은 /foo/bar 하지 존재합니다. 그것이 baz경로의 중단 점 인지 판단하는 빠른 방법이 있습니까?

Bash를 사용하고 있습니다.



답변

귀하와 같은 정식 경로 이름이 주어지면 다음과 같이 작동합니다.

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.


답변

내가 가장 좋아하는 유틸리티 중 하나는 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는 마운트 지점을 나타냅니다.


답변

이와 같은 것 (빈칸이있는 경로 이름을 고려한) :

#!/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

답변

경로가 절대 경로 (/로 시작)라고 가정하면 bash에 대한 대체 솔루션입니다.

#!/bin/bash

pathname="$1"

IFS='/' read -r -a p <<<"${pathname#/}"

pa=""    max="${#p[@]}"    i=0
while (( i<"$max" )); do
      pa="$pa/${p[i++]}"
      if     [[ ! -e $pa ]]; then
             printf 'failed at: \t"%s"\t"%s"\n' "${pa##*/}" "${pa}"
             break
      fi
done

$ ./script "/foo/ba r/baz/hello/world"
failed at:      "hello"        "/foo/ba r/baz/hello"

답변

(( 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문자 가 포함되어 있으면 작동하지 않습니다.