Відповіді:
З урахуванням канонічного імені, наприклад вашого, це буде працювати:
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.
$pathname , використовуючи set -f", який не повертається до значення за замовчуванням"
Одна з моїх улюблених утиліт - це 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перший рядок циклу while (до його збільшення). Коли тест на "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
це не просто, але ви можете помістити його в сценарій, зробити його виконуваним і вставити його кудись у свій шлях, якщо ви збираєтеся ним часто користуватися.
Caveat emptor: Якщо ім'я вашого каталогу на будь-якому рівні містить spaceсимвол, це НЕ буде працювати.
access(2)не дуже деталізований, тому рішення, як правило, передбачає написання чогось, щоб повторити і протестувати кожен елемент шляху по черзі ...