Skip to main content

Глава 5. Работа с файлами и каталогами

Работа с файлами и каталогами

Цель занятия — научиться копировать и перемещать файлы, редактировать текст, перенаправлять потоки и различать виды ссылок. Материал рассчитан на Ubuntu Server 26.04.1 LTS. Команды проверены на виртуальной машине 7 октября 2026 года. Работайте в VirtualBox под учётной записью student; имя машины соответствует её месту: 562-01–562-13.

1. Подготовка рабочего каталога

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

mkdir -p ~/chapter05/in ~/chapter05/out
cd ~/chapter05
printf 'Ubuntu Server\nРабота с файлами\n' > in/lesson.txt
ls -l in

Повторное выполнение printf с > заменит содержимое файла. Прежде чем повторять команды, проверьте, нет ли в нём сделанных вами изменений.

Запомнить: файл и каталог

Обычный файл содержит данные. Каталог связывает имена с объектами файловой системы. Полный путь начинается с /, относительный отсчитывается от текущего каталога.

2. Копирование, перемещение и переименование

У cp сначала указывают источник, затем назначение:

cp in/lesson.txt out/lesson-copy.txt
cp in/lesson.txt out/
ls -l out

Первая команда задаёт новое имя копии. Вторая помещает файл в существующий каталог и сохраняет имя. Если файл назначения существует, обычный cp может заменить его. Для учебных работ удобно запрашивать подтверждение перезаписи:

cp -i in/lesson.txt out/lesson-copy.txt
cp -a in out/in-backup

При запросе cp -i ответ y разрешает перезапись, n сохраняет прежний файл назначения. В проверенной GNU cp 9.7 отказ от перезаписи возвращает код 1. Чтобы увидеть код, выполните сразу после команды printf 'Код завершения cp: %s\n' "$?", затем проверьте содержимое назначения. Такой результат нужно отличать от согласованной и выполненной перезаписи.

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

Копирование каталогов и повторный запуск

cp -r включает рекурсивное копирование: вместе с каталогом обходятся его дочерние объекты. cp -a дополнительно сохраняет атрибуты и структуру ссылок. Для обычного каталога без одной из этих опций cp сообщит, что каталог пропущен.

Результат зависит от того, существует ли каталог назначения. Это можно увидеть в уже выполненной команде cp -a in out/in-backup:

Состояние назначения перед запуском Результат
out/in-backup отсутствует Создаётся out/in-backup с содержимым in
out/in-backup уже существует как каталог Источник помещается внутрь: появляется out/in-backup/in

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

find out/in-backup -maxdepth 2 -type f -print
cp -a in out/in-backup
find out/in-backup -maxdepth 2 -type f -print

Для копирования содержимого в уже существующий каталог применяют другую запись:

mkdir -p out/content-copy
cp -a in/. out/content-copy/
find out/content-copy -maxdepth 2 -type f -print

Здесь in/. означает содержимое каталога, включая скрытые объекты; дополнительный уровень in не создаётся. Повторное выполнение может заменить совпадающие файлы, но не удаляет лишние файлы назначения. Такое копирование не является зеркалированием.

Запомнить: рекурсивная операция

Рекурсивная операция обрабатывает каталог и вложенные объекты. Наличие каталога назначения влияет на результат cp; перед повторением команды проверяйте существующую структуру.

mv перемещает объект, а внутри одного каталога служит для переименования:

mv out/lesson-copy.txt out/lecture.txt
mv -i out/lecture.txt in/
ls -l in out

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

Несколько источников и имена с пробелами

Сначала создайте файлы и каталоги назначения:

printf 'Первый документ\n' > in/first.txt
printf 'Второй документ\n' > in/second.txt
printf 'Конспект с пробелом в имени\n' > 'in/lecture notes.txt'
mkdir -p out/batch out/moved
cp -iv in/first.txt in/second.txt 'in/lecture notes.txt' out/batch/
mv -iv out/batch/first.txt out/batch/second.txt out/moved/
ls -l out/batch out/moved

При нескольких источниках последний аргумент должен обозначать существующий каталог. -v показывает операции, -i запрашивает подтверждение замены существующего файла. Ожидаемый результат первого прохода: в out/moved находятся first.txt и second.txt, а в out/batch остаётся lecture notes.txt. Исходники в in сохранились, поскольку сначала выполнялось копирование.

Кавычки делают путь с пробелами одним аргументом. Для имени, начинающегося с дефиса, отделяют аргументы от опций через --, например cp -- ./-notes.txt out/; такой файл нужно сначала создать. Точка . обозначает текущий каталог, а не специальную опцию cp.

Удаляйте только подготовленные учебные файлы. rm -i файл запрашивает подтверждение; rmdir каталог удаляет пустой каталог. Удаление через rm обычно не отправляет файл в корзину.

Выучить: порядок аргументов

cp источник назначение — копирование; mv источник назначение — перемещение или переименование. Перед операцией проверьте pwd и путь назначения.

3. Редактирование в Nano

Сначала проверьте наличие редакторов:

command -v nano
command -v vim

Если редактор не найден, выполните sudo apt update и установите нужный пакет: sudo apt install nano или sudo apt install vim. После успешной установки повторите проверку. На проверенном стенде уже установлены Nano 8.7.1 и Vim 9.1.

Теперь вернитесь в рабочий каталог и откройте подготовленный конспект:

cd ~/chapter05
nano in/lecture.txt

Введите заголовок «Конспект занятия», затем несколько строк текста. Сохраните файл сочетанием Ctrl+O, подтвердите имя клавишей Enter и выйдите через Ctrl+X. Если файл ещё не сохранён, редактор предложит сохранить изменения.

В подсказках Nano знак ^ означает Ctrl, а M- — Meta, обычно Alt. В Nano 8 и новее Ctrl+F начинает поиск вперёд, Ctrl+B — назад, Alt+F выбирает следующее совпадение вперёд. В старых инструкциях для поиска часто указан Ctrl+W. Ориентируйтесь на подсказки установленной версии и справку Ctrl+G, поскольку сочетания могут быть переназначены. Ctrl+K вырезает строку, Ctrl+U вставляет вырезанный текст. Это внутренний буфер редактора; он не обязан совпадать с буфером обмена Windows.

cat in/lecture.txt

Для конфигурационных файлов сначала изучают назначение файла и сохраняют копию, затем редактируют с нужными правами. Не добавляйте sudo к работе со своими конспектами: иначе можно получить файлы, принадлежащие root.

4. Основные режимы Vim

Откройте другой файл:

vim in/vim-notes.txt

При запуске Vim обычно находится в нормальном режиме. Нажмите i, чтобы вводить текст, напечатайте несколько строк и нажмите Esc, чтобы вернуться к командам.

Команда Действие
i Перейти к вводу перед курсором
a, A Ввод после курсора или в конце строки
Esc Вернуться в нормальный режим
:w и Enter Сохранить
:q и Enter Выйти, если нет несохранённых изменений
:wq и Enter Сохранить и выйти
:q! и Enter Выйти, отбросив несохранённые изменения
h, j, k, l Влево, вниз, вверх, вправо
dd Удалить текущую строку
x Удалить символ под курсором
gg, G Перейти к первой или последней строке
yy, затем p Скопировать строку и вставить после текущей
u, Ctrl+R Отмена и повтор отменённого изменения
/слово и Enter Поиск вперёд; n — следующее совпадение

Для замены с подтверждением каждого совпадения используется :%s/старое/новое/gc. Двоеточие открывает командную строку Vim, % выбирает весь файл, s выполняет замену, / разделяет части, g обрабатывает все совпадения в каждой строке, c запрашивает подтверждение. Без g заменяется только первое совпадение в каждой обрабатываемой строке. Символы в шаблоне поиска могут иметь специальное значение. Не применяйте глобальные замены к системным файлам, не просмотрев совпадения.

В открытом in/vim-notes.txt введите две строки: Сервер Ubuntu. Ubuntu для занятий. и Ubuntu работает в VirtualBox. Вернитесь через Esc в нормальный режим и выполните :%s/Ubuntu/Ubuntu Server/gc. На каждом подтверждении нажмите y; n пропускает совпадение, Esc прекращает замену. Должны измениться три вхождения. Нажмите u, чтобы отменить замену, затем Ctrl+R, чтобы повторить её, и сохраните файл через :wq. Теперь файл существует для следующих упражнений.

После :wq редактор уже закрыт. Для проверки команд оболочки снова откройте сохранённый файл:

vim ~/chapter05/in/vim-notes.txt

Команда :!pwd запускает команду оболочки из Vim и показывает текущий каталог. :!ls -l ~/chapter05/in выводит список подготовленных файлов; после просмотра вернитесь в редактор по приглашению, обычно через Enter. Это запуск отдельной команды, а несохранённый текст буфера автоматически на диск не записывается.

Записать: режимы Vim

Нормальный режим предназначен для команд, режим вставки — для ввода текста, визуальный режим — для выделения. Нажатия клавиш имеют разный смысл в разных режимах; перед командой возвращайтесь через Esc в нормальный режим.

Выделение, окна и настройки Vim

Откройте уже сохранённый файл vim ~/chapter05/in/vim-notes.txt. В обычном режиме нажмите v, выделите текст движением курсора, затем y для копирования. Переместите курсор и нажмите p для вставки после него. V выделяет целые строки; Esc отменяет выделение. Команда d удаляет выделенное и сохраняет его в регистре, откуда его также можно вставить через p. Перед выходом решите, сохранять ли учебные изменения: :wq сохраняет, :q! отбрасывает несохранённые изменения.

Команды :split и :vsplit делят окно по горизонтали и вертикали. Ctrl+W, затем w переключает окна; :close закрывает текущее окно. Два окна могут показывать один буфер: изменение текста в одном видно в другом. Окно — область отображения, буфер — редактируемое содержимое файла.

:set number включает номера строк, :set nonumber отключает. Чтобы настройка сохранялась при последующих запусках, откройте nano ~/.vimrc и добавьте отдельную строку set number, сохранив существующие настройки. Стандартные настройки редактора не меняют сам текст документа.

5. Стандартные потоки

Программа обычно получает три стандартных файловых дескриптора: 0 — стандартный ввод, 1 — стандартный вывод, 2 — стандартный поток ошибок. При работе в терминале они обычно связаны с терминалом, но оболочка может изменить это соединение.

Дескриптор Название Назначение Пример перенаправления
0 stdin Данные, которые программа читает < in/lesson.txt
1 stdout Основной вывод программы > out/result.txt или 1> out/result.txt
2 stderr Диагностические сообщения 2> out/errors.txt

Дескриптор — номер открытого канала ввода-вывода в процессе. Ввод может поступать из файла, терминала или другой программы; для программы важен канал, а не только клавиатура.

cat < in/lesson.txt
wc -l < in/lesson.txt
cat in/lesson.txt > out/result.txt
printf 'Дополнительная строка\n' >> out/result.txt
cat out/result.txt

< задаёт входной файл, > создаёт или обнуляет выходной, >> дописывает в конец. Обнуление происходит ещё до запуска программы. Поэтому команда вида cat файл > файл уничтожает исходное содержимое.

Разделите нормальный вывод и ошибки:

Пример предполагает, что missing-file в текущем каталоге отсутствует. Проверьте это через ls -ld missing-file: сообщение об отсутствии здесь ожидаемо. Если объект существует, выберите для всех команд этого примера другое отсутствующее имя.

ls in/lesson.txt missing-file > out/list.txt 2> out/errors.txt
cat out/list.txt
cat out/errors.txt
ls in/lesson.txt missing-file > out/combined.txt 2>&1

В последней строке сначала stdout направляется в файл, затем stderr связывается с текущим stdout. Порядок перенаправлений важен. Запись 2>&1 > файл имеет другой результат.

Два порядка перенаправлений

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

cd ~/chapter05
ls in/lesson.txt missing-file > out/order-a.txt 2>&1
ls in/lesson.txt missing-file 2>&1 > out/order-b.txt
cat out/order-a.txt
cat out/order-b.txt
Команда Что увидите на экране при её запуске Что окажется в файле
> out/order-a.txt 2>&1 Вывод ls перенаправлен Имя существующего файла и сообщение об отсутствующем
2>&1 > out/order-b.txt Сообщение об отсутствующем файле Только имя существующего файла

Перенаправления выполняются слева направо. 2>&1 делает stderr копией текущего назначения stdout. При последующем перенаправлении stdout назначение stderr автоматически не меняется. Порядок строк в объединённом файле не гарантируется, а язык диагностического сообщения зависит от локали.

Конвейер | передаёт stdout одной команды на stdin следующей:

cat in/lesson.txt | wc -l
find in -type f -name '*.txt' | sort

Кавычки вокруг *.txt оставляют шаблон для find, а не для предварительного раскрытия оболочкой. Обычный конвейер не передаёт stderr. /dev/null позволяет отбросить поток, например команда > /dev/null, но не исправляет ошибки программы.

Вывод на экран и сохранение через tee

cat in/lesson.txt | tee out/tee-copy.txt | wc -l
cmp in/lesson.txt out/tee-copy.txt

tee записывает полученный stdin в файл и одновременно передаёт те же данные в stdout, откуда их читает wc. На экране будет количество строк исходного файла. При совпадении cmp ничего не печатает и завершается с кодом 0. Для одновременного показа самого текста и записи достаточно cat in/lesson.txt | tee out/tee-copy.txt; обычный tee заменяет файл, tee -a дописывает.

Записать: перенаправление и конвейер

Перенаправление меняет канал ввода или вывода команды. Конвейер соединяет stdout одной команды со stdin следующей. tee позволяет одновременно сохранить поток и передать его дальше.

Оболочка выполняет перенаправление своими правами. Поэтому sudo команда > защищённый-файл не даёт оболочке право записи. Когда запись с повышенными правами действительно нужна, применяют sudo tee, изучив сначала назначение файла.

Выучить: потоки и результат выполнения

stdout — основной вывод, stderr — диагностические сообщения. Наличие текста в stderr само по себе не определяет успех: результат программы выражает код завершения, доступный в Bash через $? сразу после команды.

6. Жёсткие и символические ссылки

Создайте обе ссылки на подготовленный файл:

cd ~/chapter05
ln in/lesson.txt in/lesson-hard.txt
ln -s lesson.txt in/lesson-symbolic.txt
ls -li in/lesson*.txt
readlink in/lesson-symbolic.txt

У исходного имени и жёсткой ссылки одинаковый номер inode. Это два имени одного объекта; изменение содержимого через одно имя видно через другое. Жёсткие ссылки обычно нельзя создать между разными файловыми системами или на каталог.

Одинаковый номер inode сравнивают в пределах одной файловой системы. Inode хранит тип, права, владельцев, временные метки и другие сведения; имя файла хранится в записи каталога. Число жёстких ссылок видно в колонке после прав у ls -l. Для lesson.txt и lesson-hard.txt после создания ссылки ожидается число 2, если ранее не создавались другие жёсткие ссылки.

Символическая ссылка хранит путь. Здесь относительный путь lesson.txt отсчитывается от каталога in, где находится сама ссылка, а не от текущего рабочего каталога пользователя.

mv in/lesson.txt in/lesson-renamed.txt
cat in/lesson-hard.txt
cat in/lesson-symbolic.txt

Жёсткая ссылка продолжит открывать данные. Символическая станет «оборванной»: указанного пути больше нет. Верните имя и проверьте результат:

mv in/lesson-renamed.txt in/lesson.txt
cat in/lesson-symbolic.txt

Удаление имени жёсткой ссылки не удаляет другие имена. Данные освобождаются после исчезновения последней жёсткой ссылки и последнего открытого использования файла. Удаление самой символической ссылки через rm имя-ссылки не удаляет объект назначения. Не добавляйте завершающий / при удалении ссылки на каталог.

Копия и два вида ссылок

Свойство Обычная копия файла Жёсткая ссылка Символическая ссылка
Что создаётся Отдельный объект с копией содержимого Ещё одно имя того же объекта Отдельный объект, содержащий путь
Inode Другой Тот же в той же файловой системе Собственный, отличный от цели
Изменение текста через новое имя Меняется только копия Видно через все имена этого объекта Меняет цель при переходе по ссылке
Переименование исходного имени На копию не влияет На оставшееся имя не влияет Может нарушить путь к цели
Удаление исходного имени Копия остаётся Данные доступны через оставшееся имя Ссылка остаётся, но цель по этому пути отсутствует
Переход между файловыми системами Копирование возможно Нельзя создать такую ссылку между ФС Путь может указывать на другую ФС
Ссылка на каталог Каталог можно отдельно скопировать рекурсивно Обычно запрещена Поддерживается

При сохранении файла редактор иногда заменяет его новым объектом вместо записи в прежний. Поэтому поведение жёстких ссылок при таком сохранении нужно проверять отдельно; для наглядной проверки записи в существующий объект используют дописывание через оболочку. Даже CoW-копия с первоначально общими блоками остаётся отдельным объектом с независимым содержимым после изменений.

Символическая ссылка на каталог

cd ~/chapter05
ln -s in notes-dir
ls -ld notes-dir
readlink notes-dir
cat notes-dir/lesson.txt
rm -i -- notes-dir
ls -ld in

Пример предполагает, что имя notes-dir свободно. При ошибке «File exists» сначала выясните назначение существующего объекта, не заменяйте его принудительно. Ссылка notes-dir хранит относительный путь in, который отсчитывается от ~/chapter05. После подтверждения удаляется сама ссылка, а каталог in и его документы остаются. Если переместить относительную ссылку в другой каталог, смысл её пути может измениться даже без перемещения цели.

Запомнить: inode и ссылка

Inode содержит сведения об объекте файловой системы. Жёсткая ссылка связывает имя с inode. Символическая ссылка содержит путь к другому объекту.

7. Практическое задание

Этап 1. Подготовка и конспект

Создайте отдельный каталог ~/chapter05/practice и подкаталоги source, copies, moved. Если уже выполняли итоговую работу, выберите новый свободный каталог вместо перезаписи прежних результатов. В Nano создайте source/notes.txt с определениями stdin, stdout, stderr и рекурсивного копирования. Создайте также source/network.txt и source/storage.txt с одной строкой текста в каждом. Сохраните файлы и проверьте их через cat.

Ожидаемый результат: три исходных файла существуют до копирования; конспект читается и содержит четыре определения.

Этап 2. Копирование и перемещение

Одной командой скопируйте network.txt и storage.txt в copies. Переименуйте копию network.txt в network-copy.txt и переместите её в moved. Исходники не меняйте. Объясните, почему каталог назначения нескольких источников нужно создать заранее.

Ожидаемый результат: исходные три файла остаются в source; storage.txt находится также в copies, network-copy.txt — в moved.

Этап 3. Редактирование в Vim

Сделайте отдельную копию notes.txt для тренировки. Откройте её в Vim, добавьте строку через A, перейдите к началу и концу через gg и G, скопируйте строку и выполните замену выбранного слова с подтверждением. Отмените замену через u, повторите через Ctrl+R, сохраните результат. Не меняйте исходный конспект, используемый далее для проверки ссылок.

Ожидаемый результат: тренировочная копия сохранена; студент объясняет режимы редактора, замену и отмену.

Этап 4. Потоки

Из каталога practice запустите ls для source/notes.txt и заведомо отсутствующего файла. Сохраните stdout и stderr в отдельные файлы. Затем выполните два варианта объединения потоков из раздела 5, используя новые имена результатов в copies. Через tee сделайте копию конспекта и сравните её с исходным файлом командой cmp.

Ожидаемый результат: основной вывод и ошибка разделены; показана разница порядка перенаправлений; копия tee совпадает с исходником. Сообщение об отсутствующем файле в этом опыте ожидаемо.

Этап 5. Копия и ссылки

Для source/notes.txt создайте обычную копию, жёсткую и символическую ссылки с отдельными именами в каталоге practice. Учтите, что относительный путь в символической ссылке отсчитывается от её каталога. Покажите ls -li, затем допишите строку через жёсткую ссылку с >>.

Ожидаемый результат: исходник и жёсткая ссылка имеют одинаковый inode, обычная копия и символическая ссылка — собственные. Дописанная строка видна в исходнике и при чтении через обе ссылки, но не появилась в обычной копии.

Переименуйте исходный notes.txt в notes-renamed.txt. Проверьте чтение жёсткой и символической ссылок, затем верните исходное имя. Создайте символическую ссылку на каталог source и проверьте чтение файла через неё.

Ожидаемый результат: жёсткая ссылка работает после переименования, символическая на старый путь временно нарушается и снова работает после возврата имени. Ссылка на каталог позволяет обратиться к его файлам.

Что представить в отчёте

  1. Свой hostname, пользователя student и путь каталога работы.
  2. Дерево созданных файлов или вывод find, результат копирования и перемещения.
  3. Конспект определений и сохранённую тренировочную копию из Vim.
  4. Два файла раздельных потоков и объяснение порядка 2>&1.
  5. Результат сравнения копии tee и вывод inode для копии и ссылок.
  6. Результаты чтения ссылок до переименования, после него и после восстановления имени.
  7. Краткие ответы: чем копия отличается от жёсткой ссылки; почему символическая ссылка может оборваться; почему нельзя читать файл и одновременно перенаправлять вывод в него через >.

Критерий выполнения: результат подтверждён файлами и выводом команд, а студент объясняет поведение операций. Только скриншота ввода команды недостаточно. Учебные файлы сохраняйте до проверки преподавателем.

Документация для сверки: cp в Ubuntu 26.04, Bash: перенаправления и раскрытия, Nano в Ubuntu 26.04, учебник Vim. Для ссылок дополнительно прочитайте установленную справку man ln.