Answers:
给定一个规范的路径名(例如您的路径名),它将起作用:
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
。
ns
,如果在这里使用它,将使讨论变得毫无意义。
我最喜欢的工具之一是的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
shell,只会向stderr写像这样的东西cd:cd:6: no such file or directory: not_a_directory
。实际上,用户的外壳将以用户可能已经非常熟悉的格式进行操作。无论如何,最终它几乎总是更容易和更好,只是做一些事情并让Shell根据需要处理报告。但是,这种哲学确实需要非常严格地关注返回值及其提升/保存。
假设路径是绝对路径(以/开头),则是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
这并不简单,但是如果您打算经常使用它,则可以将其放在脚本中,使其可执行并粘贴到您的路径中。
注意:如果您在任何级别的目录名称中都包含space
字符,则此操作将无效。
access(2)
不是很精细,因此解决方案通常涉及编写一些东西来依次迭代和测试每个路径元素……