Как назвать файл на самом глубоком уровне дерева каталогов

Как назвать один случайный файл на самом глубоком уровне дерева каталогов, используя основные команды и скрипты Bash?

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

find , grep , sed и awk являются приемлемыми командами.

Моя текущая попытка выглядит так и не работает:

 find -type d |  объявить COUNT = -1;  объявить P = "";  при чтении LINE;  do echo $ LINE;  объявить C;  C = $ (echo $ LINE | cut -c3- | sed "s / \ // \ n \ // g" | grep '/' -c);  echo $ C;  если [$ COUNT -gt $ C];  то пусть COUNT = $ C;  пусть P = $ LINE;  эхо «Готово»;  Fi;  сделанный

Это приведет только к каталогу.

Как это можно решить самым простым способом?

7 Solutions collect form web for “Как назвать файл на самом глубоком уровне дерева каталогов”

Это странный запрос!

Я бы использовал find + awk для захвата файла в самом глубоком каталоге:

 bash-3.2$ deepest=$(find / -type f | awk -F'/' 'NF > depth { > depth = NF; > deepest = $0; > } > > END { > print deepest; > }') 

Использование ${deepest} в вашей команде mv остается как упражнение, но следующие пять строк могут помочь вам:

 bash-3.2$ echo "${deepest}" /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/activesupport-2.3.5/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Argentina/Buenos_Aires.rb bash-3.2$ echo "${deepest%.*}" /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/activesupport-2.3.5/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Argentina/Buenos_Aires bash-3.2$ echo "${deepest%/*}" /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/activesupport-2.3.5/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Argentina bash-3.2$ echo "${deepest##*/}" Buenos_Aires.rb bash-3.2$ echo "${deepest##*.}" rb 

После обновления до вопроса:

find -type d […] « Это нашло бы только каталог. […] Как это можно решить самым простым способом?».

Поставляя -type f чтобы find все файлы ( f ), не все каталоги ( d ).

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

 find -type d | { declare COUNT=-1 declare P="" while read LINE do echo $LINE declare C=$(echo $LINE | cut -c3- | sed "s/\//\n\//g" | grep '/' -c) echo $C if [ $C -gt $COUNT ]; then let COUNT=$C; let P=$LINE; echo "Done"; fi done echo deepest: "$P" } 

Немного улучшенная версия, с отбрасыванием пропущенных вещей:

 find -type d -links 2 | ( declare COUNT=-1 P="" while IFS= read -r LINE; do declare C=$(echo $LINE | tr -cd / | wc -c) if [ $C -gt $COUNT ]; then let COUNT=$C; P=$LINE; fi done echo deepest: "$P" ) 
 find -type f | awk -F/ 'NF > maxdepth { maxdepth = NF; file = $0 }; END {print file}' 

И похоже, что это по сути то же самое, что и этот ответ на другой вопрос, который вы опубликовали, что случилось с этим / этим?

Я бы пошел с ними, хотя они будут терпеть неудачу в именах файлов, содержащих ведущие пробелы. Первый выводит только имя файла, второй – путь к этому файлу:

 find -type f | sed 's:[^/]*/: :g' | LC_ALL=C sort | head -1 | sed 's/^ *//' find -type f | sed 'h;s:[^/]*/: :g;G;s/\n/\t/' | LC_ALL=C sort | head -1 | sed 's/.*\t//' 

С zsh:

 f=(**/*(D.Oe:'REPLY=${REPLY//[^\/]}':[1])) && mv -- $f $f:h/new-name 

Мы используем zsh рекурсивное globbing ( **/* ) и glob qualifiers (...) , с D чтобы включить dot-файлы . выбирать только обычные файлы и Oe:'code' чтобы определить порядок сортировки (здесь обратный из-за верхнего регистра O ) на основе значения $REPLY после выполнения code .

В этом code текущий файл передается как $REPLY . Мы удаляем все, кроме / символов, в $REPLY , и это то, что используется для порядка сортировки. Таким образом, файл с наибольшим / сортированным последним, сначала разворачивается, и мы выбираем его первым с помощью [1] .

bash с (последним) эквивалентом инструментов GNU может быть примерно таким:

 ( export LC_ALL=C find . -type f -print0 | sed -z 'h;s:[^/]::g;G;s:[^/]::' | sort -rz | sed -z 's:/*::;q' | tr '\0' '\n' ) 
 function step () { d=$1 d=$((d+1)) res=$(find -mindepth $d -type d ! -empty) test -n "$res" && step $d || echo $((d-1)) } find -mindepth $(step 0) -type d ! -empty | head -n 1 

Рекурсивно шаг глубже и глубже в каталоги, если они содержат файл ( ! -empty ). На последнем шаге мы должны вычесть 1, и затем мы можем использовать результат во второй команде find .

Следующий сценарий печатает самые длинные пути в файловой системе и / или ниже текущего каталога, но вместо использования find он использует существующую базу данных locate (потенциально очень длинных) путей без поиска / перемещения (потенциально очень глубокого) структуры каталогов. Обратите внимание, что он подсчитывает каталоги для определения глубины, а не только длины пути (но его можно легко изменить / упростить, чтобы сделать это).

 $ cat find-longest-path.sh #!/bin/bash pattern=$1 locate -r "^${PWD}/${pattern}" \ | while read f; do printf "$(tr -cd / <<< "$f" | wc -c):$f\n"; done \ | sort -nr -t: -k1 \ | head -5 

Это печатает самые глубокие 5 путей ( head -5 ) шаблона имени файла (regexp), начиная с pwd . Выход имеет префикс глубины (т. Е. Число / в пути). Для поиска только определенного имени файла и / или шаблона в любом месте файловой системы удалите $PWD и просто locate -r /some_file$ (… и т. Д. И т. Д.).

Например,

 $ ./find-longest-path.sh 'foo.*log$' 5:/path/to/deep/path/foo-12345.log 3:/path/to/shallow/foobar.log 
  • Необходимо захватить stdout и изменить переменную по ссылке из функции в bash
  • напишите строку до ее выполнения, не записывая ее дважды
  • bash добавить путь для обработки некоторых файлов
  • Не можете использовать! $ В скрипте?
  • Сравнение и расширение брекетов
  • Как вставить вывод предыдущей команды в текущую командную строку?
  • создание переменной и присвоение значения переменной
  • Как использовать два операнда в левой части оператора сравнения в Bash
  • Что значит `. / path / command` do? (Пространство после точки, абсолютный путь)
  • Что означает «</ dev / null»?
  • Почему \ 033 сработает для таких варов, как PS1 и \ x1b, нет?
  • Interesting Posts

    Ошибка сценария загрузки chkconfig, сценарий работает хорошо вручную

    Получу ли я критические обновления безопасности, если я заблокирую CentOS yum для конкретной версии репо?

    Предоставление пользователям временного доступа к моему серверу для запуска команды

    Как я могу отсортировать этот массив чисел?

    Правило tun0 + iptables

    Получение списка сетей Wi-Fi рядом с адаптером в режиме AP

    Получить только имя активного сетевого интерфейса

    Я хочу, чтобы мой Ubuntu 9.04 / 9.10 вернулся, есть ли текущий подобный дистрибутив?

    Как удалить файл на RAID-устройстве?

    Полное шифрование диска с помощью dm-crypt (без LUKS)

    Как показать статус всех ключей-модификаторов в X11?

    Предотвращение hashdeep от пересечения точек крепления?

    создание пользователя add

    сценарий для повторения команды tshark и каждую минуту, изменяющую имя выходного файла

    Как начать обработку файла со смещением?

    Linux и Unix - лучшая ОС в мире.