存在しないパスがあると想像してください。
$ ls /foo/bar/baz/hello/world
ls: cannot access /foo/bar/baz/hello/world: No such file or directory
しかし、/foo/bar
doesが存在するとしましょう。 baz
がパスのブレークポイントであると判断する簡単な方法はありますか?
私はBashを使用しています。
Yoursなどの正規のパス名を指定すると、これは機能します。
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
に入れられます。
私のお気に入りのユーティリティの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
は、マウントポイントを示します。
パスが絶対パス(/で始まる)であると仮定した場合の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"
このようなもの(空白が埋め込まれたパス名を考慮):
#!/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
(( 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
文字が含まれている場合、これは機能しません。