Как быстро найти самый глубокий подкаталог

Этот вопрос с ответом на вопрос является скорее вопросом новизны или любопытства.

Я знаю, что это можно сделать с помощью bash-скрипта, который рекурсивно пересекает все каталоги. Однако, вероятно, это займет много часов.

Как быстро найти самый глубокий уровень каталога?

2
задан 10 November 2019 в 03:40

2 ответа

locate команда - самое быстрое

, определить местонахождение команда - Ваш друг в этом случае:

$ time locate "/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*"
/mnt/clone/home/rick/.gradle/wrapper/dists/gradle-4.6-all/bcst21l2brirad8k2ben1letg/gradle-4.6/samples/userguide/multiproject/dependencies/java/services/personService/src/main/java/org/gradle/sample/services/PersonService.java
/mnt/clone/home/rick/.gradle/wrapper/dists/gradle-4.6-all/bcst21l2brirad8k2ben1letg/gradle-4.6/samples/userguide/multiproject/dependencies/java/services/personService/src/test/java/org/gradle/sample/services/PersonServiceTest.java
/mnt/clone/home/rick/.gradle/wrapper/dists/gradle-4.6-all/bcst21l2brirad8k2ben1letg/gradle-4.6/samples/userguide/multiproject/dependencies/javaWithCustomConf/services/personService/src/main/java/org/gradle/sample/services/PersonService.java
/mnt/clone/home/rick/.gradle/wrapper/dists/gradle-4.6-all/bcst21l2brirad8k2ben1letg/gradle-4.6/samples/userguide/multiproject/dependencies/javaWithCustomConf/services/personService/src/test/java/org/gradle/sample/services/PersonServiceTest.java

real    0m1.731s
user    0m1.653s
sys     0m0.072s

Материал достаточно в /*/*, пока никакие результаты не будут показаны, затем вычтите один /*, чтобы получить самый глубокий уровень подкаталога. Файлы на самых глубоких уровнях также будут показом.

Примечание: На этой машине есть четыре различных возвращенные пути. Каждый путь содержит один файл.

<час>

Некоторые детали об определяют местонахождение

, база данных, используемая, определяет местонахождение, ежедневно обновляется кроном. Если Вы установили приложение или создали новые справочники сегодня, Вы должны обновить использование базы данных:

sudo updatedb

В Ubuntu 19.10 определить местонахождение команда больше не устанавливается по умолчанию. Надо надеяться, это возвращается в 20.04, но тем временем Вы должны установить его с:

sudo apt install mlocate

, Чтобы получить оценку locate взгляд скорости на то, что это внесло в указатель для мгновенного поиска:

$ locate -S

Database /var/lib/mlocate/mlocate.db:
    381,154 directories
    2,548,775 files
    213,049,136 bytes in file names
    92,287,412 bytes used to store database
<час>

Используя сценарий

Комментирует пункт, как люди не будут знать начальной точки. Я написал сценарий что дефолты к 50 начальным точкам уровня и работам назад оттуда. Вы можете отвергнуть с начальной точкой 6 - 126 уровней подкаталога.

Сценарий произвел:

$ time deepdir

Search point 50 levels deep: /*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*
Common path followed by unique sub-paths (deepest subdir 25 levels):
+- /mnt/clone/home/rick/.gradle/wrapper/dists/gradle-4.6-all/bcst21l2brirad8k2ben1letg/gradle-4.6/samples/userguide/multiproject/dependencies/
|--- /java/services/personService/src/main/java/org/gradle/sample/services/PersonService.java
|--- /java/services/personService/src/test/java/org/gradle/sample/services/PersonServiceTest.java
|--- /javaWithCustomConf/services/personService/src/main/java/org/gradle/sample/services/PersonService.java
|--- /javaWithCustomConf/services/personService/src/test/java/org/gradle/sample/services/PersonServiceTest.java

real    0m45.141s
user    0m44.552s
sys     0m0.588s

$ time deepdir 26

Search point 26 levels deep: /*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*
Common path followed by unique sub-paths (deepest subdir 25 levels):
  (... SNIP repeated parts ...)

real    0m6.123s
user    0m6.041s
sys     0m0.080s
  • В первый раз, когда Вы управляете сценарием, Вы не знаете, как глубоко подкаталоги идут. Поэтому дефолт 50 уровней будет занимать 43 секунды, чтобы бежать.
  • Во второй раз, когда Вы бежите, сценарий встречают известное количество + 1, и только требуется 6 секунд, чтобы бежать.
  • После второго раза, проводите строку продукции /*/*.../* и скопируйте его (меньше 1 набор) к клипборду в качестве параметра для запроса locate или другая команда.

сценарий

#!/bin/bash

# NAME: deepdir
# PATH: $HOME/askubuntu/
# DESC: Answer for: https://askubuntu.com/questions/1187624/how-to-quickly-find-the-deepest-subdirectory/1187625?noredirect=1#comment1985731_1187625
# DATE: November 11, 2019.

StartLevel=50
[[ $1 != "" ]] && StartLevel="$1"
[[ $StartLevel -gt 126 ]] && { echo Max levels 126 ; exit 1 ; }
[[ $StartLevel -lt   6 ]] && { echo Min levels   6 ; exit 2 ; }

Big="/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*" # 33
Big="$Big/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*" # 31
Big="$Big/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*" # 31
Big="$Big/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*" # 31
                                                       # Total supported: 126

# If starting level populated it is too small.
Search="${Big:0:StartLevel*2}"
echo "Search point $StartLevel levels deep: $Search"
Count=$(locate "$Search" | wc -l)
[[ $Count -gt 0 ]] && { echo "Levels too small. $Count files found" ; exit 3 ; }

# Loop backwards to find first populated level, always more than 5
for (( l=StartLevel; l>5; l-- )) ; do
    Search="${Big:0:l*2}"
    Count=$(locate "$Search" | wc -l)
    [[ $Count -gt 0 ]] && break
done

Arr=( $(locate "$Search") )

# Enhancement using Q&A: Longest common prefix of two strings in bash
#                        https://stackoverflow.com/a/17475354/6929343

Common=\
"$(IFS= удара\n'; sed -e '$!{N;s/^\(.*\).*\n\1.*$/\1\n\1/;D;}' <<<"${Arr[*]}")"
Common="${Common%/*}/"
echo "Common path followed by unique sub-paths (deepest subdir $l levels):"
echo "+- $Common"
Len="${#Common}"

for p in "${Arr[@]}" ; do
    # echo "DEBUG: $p"
    Curr="$(dirname "$p")"
    [[ $Curr != "$Last" ]] && echo "|--- /${p:$Len}"
    Last="$Curr"
done

exit 0
удара
3
ответ дан 2 December 2019 в 01:52
find -type d \
  -wholename "$(find -type d -print0 |
                tr -d --complement '/\0' |
                sort -zur |
                sed 's:/:*/*:g' |
                head -z -n1 |
                tr -d '\0' )"

Мы будем использовать find, чтобы определить местонахождение всех справочников, затем выбрать один (s) с помощью большинства разрезов на пути. Особенно мы позволим любые возможные имена включая странных персонажей, таких как новые строки, места или этажерка.

2
ответ дан 2 December 2019 в 01:52

Другие вопросы по тегам:

Похожие вопросы: