Yanıtlar:
Sizinki gibi kanonik bir yol adı verildiğinde, bu işe yarayacaktır:
set -f --; IFS=/
for p in $pathname
do [ -e "$*/$p" ] || break
set -- "$@" "$p"
done; printf %s\\n "$*"
Bu, son tam olarak var olan / erişilebilir bileşeni üzerinden yazdırır $pathname
ve bunların her birini ayrı ayrı arg dizisine koyar. Var olmayan ilk bileşen yazdırılmaz, ancak kaydedilir $p
.
Buna zıt olarak yaklaşabilirsiniz:
until cd -- "$path" && cd -
do case $path in
(*[!/]/*)
path="${path%/*}"
;; (*) ! break
esac
done 2>/dev/null && cd -
Bu, uygun şekilde geri döner veya $path
gerektiğinde azalır . Değişiklik girişiminde bulunmayı reddeder /
, ancak başarılı olursa, hem geçerli çalışma dizininizi hem de stdout olarak değiştirildiği dizini yazdırır. Akımınız $PWD
da konacaktır $OLDPWD
.
$IFS
. tam olarak böyle çalışır. burada çağrılan değişkenin $pathname
bölünmüş olarak bir yol bileşenleri dizisine genişletilmesi dışında yol adı genişletmesine tabi değildir $IFS
.
En sevdiğim araçlardan biri namei
, util-linux
genellikle Linux'ta bulunan ve bu nedenle genellikle mevcut:
$ namei /usr/share/foo/bar
f: /usr/share/foo/bar
d /
d usr
d share
foo - No such file or directory
Ancak çıktısı çok ayrıştırılabilir değildir. Yani, sadece bir şeyin eksik olduğunu belirtmek istiyorsanız, namei
yararlı olabilir.
Bir bileşene bir bağlantının mı yoksa bir bağlanma noktasının mı olduğunu ve izinlerini belirtebileceğiniz için, bir yola erişimle ilgili genel sorunları gidermek için kullanışlıdır:
$ 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
Büyük D
harf bir bağlama noktasını belirtir.
namei
bir yem olduğu sürece benim için çalışıyor, var olan bir yol, ama vermediğim bir yol verdiğimde namei: failed to stat: /usr/share/foo/bar: No such file or directory
.
Bunun gibi bir şey (gömülü boşlukları olan yol adlarını hesaba katar):
#!/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
kabuğunuz stderr'a böyle bir şey yazacaktır cd:cd:6: no such file or directory: not_a_directory
. Aslında, kullanıcının kabuğu bunu kullanıcının zaten çok tanıdık olduğu bir biçimde yapar. Neredeyse her zaman hem daha kolay hem de daha iyi sonuçta sadece bir şeyler yapmak ve kabuğun raporlamayı gerektiği gibi işlemesine izin vermek. Bu tür bir felsefe, değerlerin geri dönüşüne ve bunların tanıtımına / korunmasına çok sıkı bir dikkat gerektirir.
Sadece bash için alternatif bir çözüm, yolun mutlak bir yol olduğunu varsayarsak (/ ile başlar):
#!/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
olarak pa_prev
(o artırılır hale geçmeden) ise döngünün ilk satırı olarak. "Pa" testi başarısız olursa, pa_prev
verilen yolda son varolan dizine sahip olur .
(( 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
bu basit değildir, ancak sık sık kullanacaksanız bir komut dosyasına koyabilir, yürütülebilir hale getirebilir ve yolunuzda bir yere yapıştırabilirsiniz.
Uyarı emptor: Dizin adınız herhangi bir düzeyde bir space
karakter içeriyorsa , bu ÇALIŞMAZ.
access(2)
çok ayrıntılı değildir, bu nedenle çözüm genellikle her bir yol öğesini yinelemek ve test etmek için bir şeyler yazmayı içerir ...