Что означает рекурсия в Linux

Обновлено: 21.11.2024

Рекурсивный означает, что команда Linux или Unix работает с содержимым каталогов, и если каталог имеет подкаталоги и файлы, команда также работает с этими файлами (рекурсивно).

Как переименовать файл в Linux?

Чтобы использовать mv для переименования файла, введите mv , пробел, имя файла, пробел и новое имя, которое вы хотите присвоить файлу. Затем нажмите Enter. Вы можете использовать ls для проверки того, что файл был переименован.

Есть ли в Linux рекурсивное копирование?

Чтобы скопировать каталог в Linux, необходимо выполнить команду «cp» с параметром «-R» для рекурсивного копирования и указать исходный и целевой каталоги для копирования. В качестве примера предположим, что вы хотите скопировать каталог «/etc» в резервную папку с именем «/etc_backup».

Что делает клиент?

cp означает копию. Эта команда используется для копирования файлов, групп файлов или каталогов. Он создает точный образ файла на диске с другим именем файла. Команда cp требует в качестве аргументов не менее двух имен файлов.

Как вставить в терминал Linux?

Нажмите Ctrl + C, чтобы скопировать текст. Нажмите Ctrl + Alt + T, чтобы открыть окно терминала, если оно еще не открыто. Щелкните правой кнопкой мыши приглашение и выберите «Вставить» во всплывающем меню. Скопированный текст вставляется в приглашение.

Как мне rm каталог?

Чтобы удалить каталог и все его содержимое, включая подкаталоги и файлы, используйте команду rm с рекурсивным параметром -r . Каталоги, удаленные с помощью команды rmdir, не могут быть восстановлены, равно как и каталоги и их содержимое, удаленные с помощью команды rm -r.

Что такое команда переименования в Linux?

Команда

rename в Linux используется для переименования именованных файлов в соответствии с регулярным выражением perlexpr. Он может изменить имя нескольких файлов. Если пользователь не укажет никаких имен файлов в командной строке с помощью этой команды, он возьмет имя файла из стандартного ввода.

Как изменить имя пользователя в терминале Linux?

Процедура изменения имени компьютера в Ubuntu Linux:

  1. Введите следующую команду, чтобы отредактировать файл /etc/hostname с помощью текстового редактора nano или vi: sudo nano /etc/hostname. Удалите старое имя и задайте новое.
  2. Далее отредактируйте файл /etc/hosts: sudo nano /etc/hosts.
  3. Перезагрузите систему, чтобы изменения вступили в силу: sudo reboot.

Я ищу разницу между cp -r и cp -a . Что означает «рекурсивный» при копировании файлов из папки?

некоторые люди ищут лучшее объяснение на справочных страницах, потому что не всегда ясно, что означает описание. Мне приходилось много раз копаться и тестировать/экспериментировать, чтобы выяснить, что на самом деле происходит с конкретной командой. man-страница grep может сбить меня с толку в любой момент.

ИЛИ учитесь, задавая вопросы здесь, получая ответы понятным вам способом, а затем лучше понимаете, что и как тестировать и экспериментировать. Пожалуйста, имейте в виду, что очень часто работает у вас, не работает у меня и т. д. и т. д.

@tripledes, мой профессор вычислительной биологии сказал, что это отличный способ немного понять конкретные случаи, которые вы тестировали, не понимая основных правил. Как ученый, я могу сказать вам, что эксперименты отвечают только на те вопросы, которые вы умеете задавать.

3 ответа 3

Рекурсивный означает, что cp копирует содержимое каталогов, и если каталог имеет подкаталоги, они также копируются (рекурсивно). Без -R команда cp пропускает каталоги. -r идентичен -R в Linux, но в некоторых крайних случаях отличается от некоторых других вариантов Unix.

По умолчанию cp создает новый файл с тем же содержимым, что и старый файл, и с теми же разрешениями, но с ограничением umask; копия датируется временем копирования и принадлежит пользователю, делающему копию. С параметром -p копия имеет такое же время модификации, такое же время доступа и те же разрешения, что и оригинал. У него также тот же владелец и группа, что и у оригинала, если у пользователя, делающего копию, есть разрешение на создание таких файлов.

Опция -a означает -R и -p , а также несколько других параметров сохранения. Он пытается создать копию, максимально приближенную к оригиналу: то же дерево каталогов, те же типы файлов, то же содержимое, те же метаданные (время, разрешения, расширенные атрибуты и т. д.).

Мой вопрос: почему необходимо использовать флаг -r (рекурсивный) при создании копии каталога? То есть, зачем это делать:

Когда мне не нужно такое поведение при копировании каталога?

Разве рекурсивная копия каталога не является поведением по умолчанию? поведение, которого мы хотим почти всегда?

Кажется, это лишний флаг.

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

@blogger Это было запрограммировано давно, но не просто так. Это означает, что если кто-то хочет выполнять базовую работу в среде командной строки, его задача должна быть настолько простой, насколько сложно избежать сбоя системы. Это означает, что есть веские причины, по которым существуют некоторые соглашения о взаимодействии с пользователем в командной строке. Я расширяю эту концепцию в своем ответе.

8 ответов 8

Как работают файловые системы, каталог на самом деле является не папкой, содержащей файлы, а каталогом, который представляет собой файл, содержащий указатели inode на связанные с ним «дочерние» файлы. Это означает, что с точки зрения файловой системы файл — это файл, а каталог — это просто файл, содержащий список подключенных файлов.

Итак, с точки зрения командной строки делаем следующее:

В основном это означает копирование файла с именем dir1 в новый файл с именем copyDir1 . Что касается файловой системы, dir1 в любом случае является просто файлом; тот факт, что это «каталог», будет очевиден только тогда, когда файловая система действительно проверит dir1, чтобы увидеть, что на самом деле представляет собой эта куча битов.

Флаг -r указывает файловой системе рекурсивно свернуть дерево файлов/каталогов и скопировать все содержимое, которое может быть «дочерним» для этого файла, в новое место.

Теперь, почему это может показаться излишним или избыточным, это действительно сводится к историческим методам работы с файловыми системами. А также создание системы, защищенной от всех типов ошибок, связанных с пользователем; случайно, так и преднамеренно.

То есть, скажем, у вас есть файл ~/bin в вашем домашнем каталоге, который вы хотите скопировать, но случайно пропустили ~ — потому что вы человек и делаете ошибки — так что это просто /bin вот так:

Благодаря «защитной сетке» каталога /bin в сочетании с необходимостью использования флага -r вы избежите случайного копирования всего двоичного корня системы, в которой вы находитесь, в ваш домашний каталог. Если бы этой страховки не существовало, произошла бы небольшая или, возможно, крупная катастрофа.

Логика здесь заключается в том, что в те дни, когда еще не было GUI (графических пользовательских интерфейсов), необходимо было установить логические/поведенческие соглашения, чтобы избежать сбоев, создаваемых пользователем, которые потенциально могут убить систему. И использование флага -r теперь является одним из них.

Если это кажется излишним, то не нужно ничего искать, кроме современной системы с графическим интерфейсом, которую можно разместить над файловыми системами Linux. Графический интерфейс решает основные проблемы пользователей, подобные этой, позволяя с легкостью перетаскивать файлы и каталоги.

Но в случае с текстовыми интерфейсами большая часть «взаимодействия с пользователем» в этом мире — это, по сути, просто логические и основанные на законах неровности дороги, которые помогают держать пользователя под контролем, чтобы предотвратить потенциальную катастрофу.

Именно поэтому файловые системы Linux/Unix не имеют разрешений 777 и прав sudo, установленных по умолчанию, и как настоящие системные администраторы вздрагивают, когда пользователь устанавливает разрешения 777 или предоставляет всем права sudo. Это основные вещи, которые нужно сделать, чтобы система была стабильной и максимально «защищенной для пользователя»; любой, кто спешит обойти эти условности, скорее всего, нанесет ущерб своей системе, даже не подозревая об этом.

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ: Другой ответ здесь, на сайте Unix Stack Exchange, дает хорошее объяснение того, почему нерекурсивная копия каталога проблематична; выделение мое.

Ну, без флага -R возможно только копирование файлов, потому что довольно необычно, что кто-то хочет нерекурсивно скопировать каталог: нерекурсивное копирование просто приведет к второму имени для каталог, указывающий непосредственно на ту же структуру каталогов. Поскольку это редко требуется людям, и на самом деле для этого существует отдельная программа (ln), нерекурсивное копирование каталогов запрещено.

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

Я понимаю, что ls -R отображает список каталогов. Но почему он рекурсивный? Как в процессе используется рекурсия?

Интуиция такова, что каталоги и их подкаталоги можно легко смоделировать с помощью дерева. Алгоритмы обхода деревьев обычно рекурсивны.

@Kevin Я не думаю, что есть необходимость ссылаться на концепцию деревьев, чтобы ответить на каждый вопрос - ответ прост: когда ls встречает каталог, он рекурсивно отображает этот каталог.

5 ответов 5

Когда мы делаем ls , мы получаем вывод только базовой папки:

Однако, когда мы вызываем ls -R , мы получаем нечто другое:

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

Или в псевдокоде:

И поскольку я могу, эталонная реализация того же Java.

По сути, вы можете задать два тесно связанных вопроса.

  • Почему процесс перехода к каждой записи в иерархии файловой системы по своей сути является рекурсивным процессом? Об этом говорится в других ответах, таких как Zanna и Kaz Wolfe.
  • Как используется техника рекурсии в реализации ls ? Из вашей фразы («Как в процессе используется рекурсия?») Я думаю, что это часть того, что вы хотите знать. Этот ответ касается этого вопроса.

Почему имеет смысл реализовать ls с помощью рекурсивной техники:

Когда функция (или процедура) вызывает сама себя. Такая функция называется «рекурсивной». Если вызов осуществляется через одну или несколько других функций, то эта группа функций называется «взаимно-рекурсивной».

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

Во время обработки параметра ls определит, был ли запрос на рекурсивную работу (путем вызова с флагом -R). Если это так, функция, которая создает список отображаемых записей, будет вызывать себя один раз для каждого каталога, который она перечисляет, за исключением . а также .. . Могут быть отдельные рекурсивные и нерекурсивные версии этой функции, или функция может каждый раз проверять, должна ли она работать рекурсивно.

Ubuntu /bin/ls , исполняемый файл, который запускается при запуске ls , предоставляется GNU Coreutils и имеет много функций. В результате его код несколько длиннее и сложнее, чем можно было ожидать. Но Ubuntu также содержит более простую версию ls, предоставленную BusyBox. Вы можете запустить это, набрав busybox ls .

Как Busybox ls использует рекурсию:

ls в BusyBox реализован в coreutils/ls.c . Он содержит функцию scan_and_display_dirs_recur(), которая вызывается для рекурсивной печати дерева каталогов:

Строка, в которой происходит рекурсивный вызов функции:

Наблюдение за рекурсивными вызовами функций по мере их возникновения:

Вы можете увидеть это в действии, если запустите busybox ls в отладчике. Сначала установите символы отладки, включив пакеты -dbgsym.ddeb, а затем установив пакет busybox-static-dbgsym. Также установите gdb (это отладчик).

Я предлагаю отлаживать coreutils ls в простом дереве каталогов.

Если у вас его нет под рукой, сделайте его (это работает так же, как команда mkdir -p в ответе WinEunuuchs2Unix):

И заполните его несколькими файлами:

Вы можете убедиться, что команда busybox ls -R foo работает должным образом, выдав следующий результат:

Откройте busybox в отладчике:

GDB напечатает некоторую информацию о себе. Затем он должен сказать что-то вроде:

(gdb) — это ваша подсказка в отладчике. Первое, что вы скажете GDB сделать в этом приглашении, это установить точку останова в начале функции scan_and_display_dirs_recur():

Когда вы запустите это, GDB должен сказать вам что-то вроде:

Теперь скажите GDB запустить busybox с аргументами ls -R foo (или любым другим именем каталога):

Вы можете увидеть что-то вроде этого:

Если вы видите Нет такого файла или каталога, как указано выше, ничего страшного. Цель этой демонстрации — просто увидеть, когда была вызвана функция scan_and_display_dirs_recur(), поэтому GDB не нужно проверять фактический исходный код.

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

Чтобы продолжить работу GDB, выполните:

Каждый раз, когда вызывается функция scan_and_display_dirs_recur(), точка останова будет срабатывать снова, так что вы сможете увидеть рекурсию в действии. Это выглядит так (включая подсказку (gdb) и ваши команды):

Функция повторяется в названии. BusyBox использует его только тогда, когда задан флаг -R? В отладчике это легко узнать:

Даже без -R эта конкретная реализация ls использует ту же функцию, чтобы узнать, какие записи файловой системы существуют, и показать их.

Если вы хотите выйти из отладчика, просто скажите ему:

Как функция scan_and_display_dirs_recur() узнает, следует ли вызывать себя:

Как конкретно это работает при передаче флага -R? Изучение исходного кода (это может быть не точная версия в вашей системе Ubuntu) показывает, что он проверяет свою внутреннюю структуру данных G.all_fmt , где хранятся параметры, с которыми он был вызван:

(Если BusyBox был скомпилирован без поддержки -R , он также не будет пытаться рекурсивно отображать записи файловой системы; об этом говорится в части ENABLE_FEATURE_LS_RECURSIVE.)

Только когда G.all_fmt и DISP_RECURSIVE имеют значение true, запускается код, содержащий вызов рекурсивной функции.

В противном случае функция запускается только один раз (для каталога, указанного в командной строке).

Читайте также: