Відповіді:
З урахуванням канонічного імені, наприклад вашого, це буде працювати:
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)
не дуже деталізований, тому рішення, як правило, передбачає написання чогось, щоб повторити і протестувати кожен елемент шляху по черзі ...