Как пройти каталоги, из которых состоит путь в BASH
Я собираюсь запрограммировать анализатор файлов, работающий в древовидной структуре каталогов. Как только я нахожу конкретный конечный каталог, я хочу просмотреть все каталоги, из которых состоит путь, и выполнить в них некоторые операции.
Допустим, путь: /d1/d2/d3
, Теперь я хочу проверить, есть ли файл x
присутствует в /d1
, /d1/d2
а также /d1/d2/d3
соответственно и в таком порядке.
Конечно, можно сделать что-то вроде этого:
fields=`find $base_dir -name "leaf_directory" | grep -o "/" | wc -l`
[[ $fields > 0 ]] || exit 1
for (( i=1; i <= $fields + 1; i++ )) do
current_dir="`find $base_dir -name "leaf_directory" | cut -d "/" -f $i`"
source_path="$source_path$current_dir/"
if [ -f $source_path$file ]; then
# do sth.
fi
done
Но есть ли более элегантное решение для этого?
Спасибо.
3 ответа
Пожалуйста, попробуйте следующее:
path="aa/bb/cc"
file="x"
while true; do
if [[ -f "$path/$file" ]]; then
echo "Found: $path/$file"
fi
if [[ $path =~ ^/?[^/]+$ ]]; then
break
fi
path="${path%/*}"
done
Все сводится к проблеме, как генерировать верхние каталоги по заданному пути. Мой код выше будет работать для обоих случаев абсолютного пути и относительного пути. Чтобы принять путь, который начинается с .
или же ..
потребуется небольшое изменение в регулярном выражении.
[РЕДАКТИРОВАТЬ]
Если вы хотите обработать заказ как aa
, aa/bb
Пожалуйста, попробуйте следующее:
path="aa/bb/cc"
file="x"
while true; do
array+=("$path")
if [[ $path =~ ^/?[^/]+$ ]]; then
break
fi
path="${path%/*}"
done
for (( i=${#array[@]}-1; i>=0; i-- )); do
p="${array[$i]}"
if [[ -f "$p/$file" ]]; then
echo "Found: $p/$file"
fi
done
[РЕДАКТИРОВАТЬ]
Если вы хотите включить корневой каталог /
в пути поиска, когда указан абсолютный путь, попробуйте:
path="/aa/bb/cc"
file="x"
while true; do
array+=("$path")
if [[ $path =~ ^(/|[^/]+)$ ]]; then
break
elif [[ $path =~ ^/[^/]+$ ]]; then
path="/"
else
path="${path%/*}"
fi
done
for (( i=${#array[@]}-1; i>=0; i-- )); do
p="${array[$i]}"
if [[ -f "$p/$file" ]]; then
echo "Found: $p/$file"
fi
done
Теперь я нашел другое решение, используя внутренний разделитель полей. /
Каталог также считается.
path="/d1/d2/d3"
file=x
IFS='/'
unset current_path
for current_dir in $path; do
current_path="${current_path}${current_dir}/"
if [ -f "${current_path}${file}" ]; then
printf '%s\n' "$current_path"
fi
done
unset IFS
Это то, что вы пытаетесь сделать (не проверено)?
fullPath='first/second/third'
mapfile -t -d '/' dirs <<<"${fullPath}/"
numDirs=$(( ${#dirs[@]} - 1 ))
path=''
file='x'
for (( dirNr=1; dirNr<=numDirs; dirNr++ )); do
path="${path}${dirs[$dirNr]}/"
if [[ -f "${path}${file}" ]]; then
printf 'Found "%s"\n' "${path}${file}"
fi
done