Risposte:
Dato un percorso canonico, come il tuo, funzionerà:
set -f --; IFS=/
for p in $pathname
do [ -e "$*/$p" ] || break
set -- "$@" "$p"
done; printf %s\\n "$*"
Che stampa attraverso l'ultimo componente completamente esistente / accessibile di $pathnamee mette ciascuno di questi separatamente nell'array arg. Il primo componente inesistente non viene stampato, ma viene salvato in $p.
Potresti affrontarlo in modo opposto:
until cd -- "$path" && cd -
do case $path in
(*[!/]/*)
path="${path%/*}"
;; (*) ! break
esac
done 2>/dev/null && cd -
Che tornerà in modo appropriato o ridurrà $pathse necessario. Rifiuta di tentare una modifica /, ma in caso di successo stamperà sia la directory di lavoro corrente sia la directory in cui passa a stdout. $PWDVerrà inserita anche la tua corrente $OLDPWD.
for p in $pathname sarà soggetto a "suddivisione delle parole" e "espansione del percorso".
$IFS. funziona esattamente così. non è soggetto all'espansione del nome percorso, tranne per il fatto che la variabile qui chiamata $pathnameviene espansa in una matrice di componenti percorso come suddivisa $IFS.
$pathname usando set -f"che non viene riportato al suo valore predefinito.
Una delle mie utility preferite è namei, parte di util-linuxe quindi generalmente presente solo su Linux:
$ namei /usr/share/foo/bar
f: /usr/share/foo/bar
d /
d usr
d share
foo - No such file or directory
Ma il suo output non è molto analizzabile. Quindi, se desideri solo sottolineare che manca qualcosa, nameipotrebbe essere utile.
È utile per la risoluzione dei problemi generali di accesso a un percorso, poiché è possibile indurlo a indicare se un componente è un collegamento o un punto di montaggio, nonché le relative autorizzazioni:
$ 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
La capitale Dindica un punto di montaggio.
nameifunziona per me fintanto che lo alimenta un percorso che esiste, ma quando lo do uno che non lo capisco namei: failed to stat: /usr/share/foo/bar: No such file or directory.
Qualcosa del genere (tenendo conto dei nomi dei percorsi con spazi vuoti incorporati):
#!/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_directorytua shell scriverà a stderr qualcosa del genere cd:cd:6: no such file or directory: not_a_directory. In realtà, la shell dell'utente lo farà in un formato con cui probabilmente l'utente ha già molta familiarità. È quasi sempre più facile e migliore alla fine, comunque, fare semplicemente cose e lasciare che la shell gestisca i rapporti, se necessario. Questo tipo di filosofia richiede tuttavia un'attenzione molto rigorosa per restituire valori e la promozione / conservazione degli stessi.
Solo una soluzione alternativa per bash, supponendo che il percorso sia un percorso assoluto (inizia con /):
#!/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"
pacome pa_prevprima riga del ciclo while (prima che venga incrementato). Quando il test per "pa" fallisce, pa_prevha l'ultima directory esistente nel percorso indicato.
(( 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
non è semplice ma puoi inserirlo in uno script, renderlo eseguibile e incollarlo da qualche parte nel tuo percorso, se lo utilizzerai frequentemente.
Avvertenza: se il nome della directory a qualsiasi livello contiene un spacecarattere, NON funzionerà.
access(2)non è molto granulare, quindi la soluzione prevede in genere di scrivere qualcosa per iterare e testare ogni elemento del percorso a sua volta ...