Как обойти дерево каталогов в Linux
Опубликовано: 2022-07-21
Каталоги в Linux позволяют группировать файлы в отдельные коллекции. Недостатком является утомительное перемещение из каталога в каталог для выполнения повторяющейся задачи. Вот как это автоматизировать.
Все о каталогах
Первая команда, которую вы выучите при знакомстве с Linux, вероятно, ls
, но cd
не отстает от нее. Понимание каталогов и того, как перемещаться по ним, особенно по вложенным подкаталогам, является фундаментальной частью понимания того, как Linux организует себя, и как вы можете организовать свою работу в файлах, каталогах и подкаталогах.
Понимание концепции дерева каталогов и того, как перемещаться между ними, — это одна из многих небольших вех, которые вы проходите, знакомясь с ландшафтом Linux. Используя cd
с путем, вы попадете в этот каталог. Ярлыки, такие как cd ~
или cd
сами по себе, возвращают вас в ваш домашний каталог, а cd ..
перемещает вас на один уровень вверх в дереве каталогов. Простой.
Однако не существует столь же простого способа запуска команды во всех каталогах дерева каталогов. Существуют разные способы достижения этой функциональности, но нет стандартной команды Linux, предназначенной для этой цели.
Некоторые команды, такие как ls
, имеют параметры командной строки, которые заставляют их работать рекурсивно , то есть они начинаются в одном каталоге и методично работают со всем деревом каталогов ниже этого каталога. Для ls
это опция -R
(рекурсивная).
Если вам нужно использовать команду, которая не поддерживает рекурсию, вы должны сами обеспечить рекурсивную функциональность. Вот как это сделать.
СВЯЗАННЫЕ: 37 важных команд Linux, которые вы должны знать
Команда дерева
Команда tree
не поможет нам в решении поставленной задачи, но позволяет легко увидеть структуру дерева каталогов. Он рисует дерево в окне терминала, чтобы мы могли получить мгновенный обзор каталогов и подкаталогов, составляющих дерево каталогов, и их относительное положение в дереве.
Вам нужно будет установить tree
.
В Ubuntu вам нужно ввести:
дерево установки sudo apt
В Fedora используйте:
дерево установки sudo dnf
На Manjaro команда такая:
sudo pacman-Sy дерево
Использование tree
без параметров рисует дерево под текущим каталогом.
дерево
Вы можете передать путь к tree
в командной строке.
работа с деревом
Параметр -d
(каталоги) исключает файлы и показывает только каталоги.
дерево -d работа
Это наиболее удобный способ получить четкое представление о структуре дерева каталогов. Показанное здесь дерево каталогов используется в следующих примерах. Есть пять текстовых файлов и восемь каталогов.
Не разбирать вывод из ls в обход каталогов
Ваша первая мысль может заключаться в том, что если ls
может рекурсивно перемещаться по дереву каталогов, почему бы не использовать ls
именно для этого и направить вывод в некоторые другие команды, которые анализируют каталоги и выполняют некоторые действия?
Разбор вывода ls
считается плохой практикой. Из-за возможности Linux создавать имена файлов и каталогов, содержащие всевозможные странные символы, становится очень сложно создать универсальный, универсальный синтаксический анализатор.
Возможно, вы никогда не создадите сознательно такое нелепое имя каталога, но ошибка в сценарии или приложении может.
Анализ законных, но плохо продуманных имен файлов и каталогов подвержен ошибкам. Есть и другие методы, которые мы можем использовать, более безопасные и более надежные, чем интерпретация вывода ls
.
Использование команды поиска
Команда find
имеет встроенные рекурсивные возможности, а также может запускать команды для нас. Это позволяет нам создавать мощные однострочники. Если это то, что вы, вероятно, захотите использовать в будущем, вы можете превратить свою однострочную строку в псевдоним или функцию оболочки.
Эта команда рекурсивно просматривает дерево каталогов в поисках каталогов. Каждый раз, когда он находит каталог, он выводит имя каталога и повторяет поиск внутри этого каталога. Завершив поиск в одном каталоге, он выходит из этого каталога и возобновляет поиск в своем родительском каталоге.
найти работу -тип d -execdir эхо "В:" {} \;
По порядку, в котором перечислены каталоги, вы можете видеть, как поиск продвигается по дереву. Сравнив вывод команды tree
с выводом однострочной команды find
, вы увидите, как find
ищет каждый каталог и подкаталог по очереди, пока не наткнется на каталог без подкаталогов. Затем он возвращается на уровень вверх и возобновляет поиск на этом уровне.
Вот как составляется команда.
- find : команда
find
. - work : Каталог для начала поиска. Это может быть путь.
- -type d : Мы ищем каталоги.
- -execdir : мы собираемся выполнить команду в каждом найденном каталоге.
- echo «In:» {} : это команда. Мы просто повторяем имя каталога в окне терминала. «{}» содержит имя текущего каталога.
- \; : Это точка с запятой, используемая для завершения команды. Нам нужно экранировать его с помощью обратной косой черты, чтобы Bash не интерпретировал его напрямую.
С небольшим изменением мы можем заставить команду find возвращать файлы, соответствующие ключу поиска. Нам нужно включить опцию -name и подсказку для поиска. В этом примере мы ищем текстовые файлы, соответствующие «*.txt», и выводим их имя в окно терминала.

find work -name "*.txt" -type f -execdir echo "Найдено:" {} \;
Ищете ли вы файлы или каталоги, зависит от того, чего вы хотите достичь. Чтобы запустить команду внутри каждого каталога , используйте -type d
. Чтобы выполнить команду для каждого подходящего файла , используйте -type f
.
Эта команда подсчитывает строки во всех текстовых файлах в начальном каталоге и подкаталогах.
найти работу -имя "*.txt" -тип f -execdir wc -l {} \;
СВЯЗАННЫЕ С: Как использовать команду find в Linux
Обход дерева каталогов с помощью скрипта
Если вам нужно просмотреть каталоги внутри скрипта, вы можете использовать команду find
внутри вашего скрипта. Если вам нужно — или вы просто хотите — выполнить рекурсивный поиск самостоятельно, вы тоже можете это сделать.
#!/бин/баш shopt -s dotglob nullglob функция рекурсивная { локальный текущий_каталог dir_or_file для current_dir в $1; делать echo "Команда каталога для:" $current_dir для dir_or_file в "$current_dir"/*; делать если [[ -d $dir_or_file ]]; тогда рекурсивный "$dir_or_file" еще wc $dir_or_file фи Выполнено Выполнено } рекурсивный "$1"
Скопируйте текст в редактор и сохраните его как «recurse.sh», затем используйте команду chmod
, чтобы сделать его исполняемым.
chmod +x recurse.sh
Сценарий устанавливает два параметра оболочки, dotglob
и nullglob
.
Параметр dotglob
означает, что имена файлов и каталогов начинаются с точки « .
” будет возвращено при раскрытии условий поиска с подстановочными знаками. Фактически это означает, что мы включаем скрытые файлы и каталоги в наши результаты поиска.
Параметр nullglob
означает, что шаблоны поиска, которые не находят никаких результатов, обрабатываются как пустая или нулевая строка. По умолчанию они не соответствуют самому поисковому запросу. Другими словами, если мы ищем все в каталоге, используя подстановочный знак звездочки « *
», но результатов нет, мы получим нулевую строку вместо строки, содержащей звездочку. Это предотвращает непреднамеренную попытку сценария открыть каталог с именем «*» или трактовать «*» как имя файла.
Затем он определяет функцию, называемую recursive
. Здесь происходят интересные вещи.
Объявляются две переменные, называемые current_dir
и dir_or_file
. Это локальные переменные, и на них можно ссылаться только внутри функции.
Внутри функции также используется переменная с именем $1
. Это первый (и единственный) параметр, передаваемый функции при ее вызове.
Скрипт использует два цикла for
, один из которых вложен в другой. Первый (внешний) цикл for
используется для двух целей.
Один из них — запустить любую команду, которую вы хотите выполнить в каждом каталоге. Все, что мы здесь делаем, это вывод имени каталога в окно терминала. Конечно, вы можете использовать любую команду или последовательность команд или вызвать другую функцию сценария.
Второе, что делает внешний цикл for, — это проверка всех объектов файловой системы, которые он может найти, будь то файлы или каталоги. Это цель внутреннего цикла for
. В свою очередь, имя каждого файла или каталога передается в переменную dir_or_file
.
Затем переменная dir_or_file
проверяется в операторе if, чтобы определить, является ли она каталогом.
- Если это так, функция вызывает себя и передает имя каталога в качестве параметра.
- Если переменная
dir_or_file
не является каталогом, то это должен быть файл. Любые команды, которые вы хотите применить к файлу, могут быть вызваны из предложенияelse
оператораif
. Вы также можете вызвать другую функцию в том же скрипте.
Последняя строка сценария вызывает recursive
функцию и передает первый параметр командной строки $1
в качестве начального каталога для поиска. Это то, с чего начинается весь процесс.
Запустим скрипт.
./recurse.sh работает
Каталоги просматриваются, и точка в скрипте, где команда будет запускаться в каждом каталоге, указывается строками «Directory command for:». Для найденных файлов выполняется команда wc
для подсчета строк, слов и символов.
Первый обрабатываемый каталог — это «рабочий», за которым следуют все вложенные ветки каталогов дерева.
Интересно отметить, что вы можете изменить порядок, в котором обрабатываются каталоги, переместив команды, относящиеся к каталогу, из над внутренним циклом for в ниже его.
Давайте переместим строку «Directory command for:» после done
внутреннего цикла for
.
#!/бин/баш shopt -s dotglob nullglob функция рекурсивная { локальный текущий_каталог dir_or_file для current_dir в $1; делать для dir_or_file в "$current_dir"/*; делать если [[ -d $dir_or_file ]]; тогда рекурсивный "$dir_or_file" еще wc $dir_or_file фи Выполнено echo "Команда каталога для:" $current_dir Выполнено } рекурсивный "$1"
Теперь запустим скрипт еще раз.
./recurse.sh работает
На этот раз к каталогам сначала применяются команды с самых глубоких уровней, работая с ветвями дерева. Каталог, переданный сценарию в качестве параметра, обрабатывается последним.
Если важно, чтобы в первую очередь обрабатывались более глубокие каталоги, вот как вы можете это сделать.
Рекурсия — это странно
Это все равно, что звонить самому себе на собственный телефон и оставлять сообщение для себя, чтобы сказать себе, когда вы встретитесь в следующий раз — неоднократно.
Может потребоваться некоторое усилие, прежде чем вы поймете его преимущества, но когда вы это сделаете, вы увидите, что это программно элегантный способ решения сложных проблем.
СВЯЗАННЫЕ С: Что такое рекурсия в программировании и как вы ее используете?