답변:
귀하와 같은 정식 경로 이름이 주어지면 다음과 같이 작동합니다.
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
.
$IFS
. 그것이 정확히 작동하는 방식입니다. 여기에서 호출 $pathname
된 변수가에서 분할 된 경로 구성 요소의 배열로 확장 된다는 점을 제외하고는 경로 이름 확장이 적용되지 않습니다 $IFS
.
내가 가장 좋아하는 유틸리티 중 하나는 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
는 마운트 지점을 나타냅니다.
namei
피드에 존재하는 경로를 제공하는 한 나를 위해 작동하지만 얻을 수없는 경로를 제공하면 namei: failed to stat: /usr/share/foo/bar: No such file or directory
.
이와 같은 것 (빈칸이있는 경로 이름을 고려한) :
#!/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
cd not_a_directory
의 쉘이 stderr에 다음과 같은 것을 쓸 것 cd:cd:6: no such file or directory: not_a_directory
입니다. 실제로, 사용자의 쉘은 사용자가 이미 매우 친숙한 형식으로 수행합니다. 어쨌든 결국에는 작업을 수행 하고 셸이 필요에 따라보고를 처리하도록 하기 위해 거의 항상 더 쉽고 더 좋습니다 . 그러나 이러한 철학은 가치를 반환하고이를 촉진 / 보전하기 위해 매우 엄격한주의를 기울여야합니다.
경로가 절대 경로 (/로 시작)라고 가정하면 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"
pa
했습니다 pa_prev
(증가되기 전에). "pa"에 대한 테스트가 실패 pa_prev
하면 주어진 경로에 마지막 기존 디렉토리가 있습니다.
(( 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
문자 가 포함되어 있으면 작동하지 않습니다.
access(2)
매우 세분화되지 않았으므로 솔루션에는 일반적으로 각 경로 요소를 반복적으로 테스트하고 테스트 할 무언가를 작성하는 것이 포함됩니다.