В данном сценарии оболочки мне нужно взять известный путь и проверить его вверх (до корня файловой системы) для правильных разрешений. Как бы я разделил путь и пошел вверх по сценарию оболочки (может быть bash или "более низкий общий знаменатель")?
5 ответов
Когда я попробовал awk-решение ennuikiller, оно пропустило текущий каталог для меня.
Итак, пока немного поздно, вот решение только для bash:
foo=`pwd`
while [ "$foo" != "" ]; do
echo $foo # work with directory here
foo=${foo%/*}
done
Не знаю, самое ли это элегантное решение, но оно работает. Я нашел простое объяснение манипуляции со строками в tldp и обернул вокруг него цикл.
Чтобы расширить решение ennuikiller:
realpath () {
# realpath() -- print absolute path (os.path.realpath) to $1
# note: OSX does not have readlink -f
python -c "import os,sys; print(os.path.realpath(os.path.expanduser(sys.argv[1])))" "${1}"
return
}
walkpath () {
# walkpath() -- walk down path $1 and $cmd each component
# $1 : path (optional; default: pwd)
# $2 : cmd (optional; default: ls -ald --color=auto)
#https://superuser.com/a/65076
dir=${1:-$(pwd)}
if [ $(uname) == "Darwin" ]; then
cmd=${2:-"ls -ldaG"}
else
cmd=${2:-"ls -lda --color=auto"}
fi
dir=$(realpath ${dir})
parts=$(echo ${dir} \
| awk 'BEGIN{FS="/"}{for (i=1; i < NF+2; i++) print $i}')
paths=('/')
unset path
for part in $parts; do
path="$path/$part"
paths=("${paths[@]}" $path)
done
${cmd} ${paths[@]}
}
В Bash с путем, указанным в переменной оболочки (например, $ DIR), вы всегда можете получить последний (самый низкий) компонент пути, используя команду basename
а оставшийся путь - с помощью команды dirname
:
DIR="/home/user/mail/work/spam"
LAST="$( basename "$DIR" )"
DIR=""$( dirname "$DIR" )"
приводит к $DIR=/home/user/mail/work
и $LAST=spam
Но зачем использовать переменные, когда вы можете просто пройти по самому пути:
while [ "/" \!= $(pwd) ] ; do
(chmod|setfacl|do_anything) .
cd .. ;
done
Это должно работать:
unset path
parts=$(pwd | awk 'BEGIN{FS="/"}{for (i=1; i < NF; i++) print $i}')
for part in $parts
do
path="$path/$part"
ls -ld $path # do whatever checking you need here
done
В Linux вы можете использовать утилиту namei
которая включена в util-linux, чтобы получить список стандартных разрешений Unix:
namei -v path
Ниже приведен еще один сценарий, который не содержит ошибок и должен выполняться в любой современной оболочке, похожей на Bourne. Для разложения пути используется стандартная команда dirname
для постепенного удаления последнего компонента до /
или .
отдыхает (и путь больше не меняется). Просто поместите любой код вместо ls -ld
для выполнения на всех компонентах пути (например, getfacl
).
#!/bin/sh
f="$1"
p=
while test "$f" != "$p" ; do
ls -ld "$f"
p="$f"
f="$(dirname "$f")"
done