Файлы, каталоги и поиск без случайного удаления
Вы получили папку проекта: исходники, заметки, журналы и несколько копий отчёта. Нужно найти текстовый файл, сохранить прежнюю версию и переименовать результат. Если начать с команды удаления по широкому шаблону, легко потерять полезный файл. Сначала научимся выбирать объекты и проверять действие до изменения.
В прошлом уроке shell передавал точный путь как аргумент. Здесь добавим операции файловой системы. Все изменения выполняем в новой собственной папке. Практика занимает примерно двадцать минут; после неё вы сможете объяснить разницу между копией и ссылкой и искать файлы без разбора вывода ls.
Создание и чтение
lab_dir=$(mktemp -d)
cd "$lab_dir"
mkdir -p project/src project/docs project/logs
printf 'first version\n' > project/docs/notes.txt
printf 'ready\n' > 'project/docs/release notes.txt'
ls -la project/docs
cat project/docs/notes.txtmkdir -p создаёт недостающие каталоги пути. ls показывает имена и метаданные; cat — содержимое. Время, владелец и размер зависят от среды. Точка перед именем делает его скрытым для обычного ls, но не создаёт защиту. ls -a показывает такие имена тоже.
Текст можно менять в редакторе. В Ubuntu команда nano project/docs/notes.txt открывает файл, если nano установлен. Нижняя строка подсказывает сочетания: Ctrl+O сохраняет, Enter подтверждает имя, Ctrl+X выходит. Обозначение ^ означает Ctrl, а не буквальный символ. Если редактор отсутствует, используйте уже изученный printf для маленького учебного файла; установку разберём позже. Не открывайте системную конфигурацию для этого опыта.
Копия и перемещение
cp project/docs/notes.txt project/docs/notes.backup
mv project/docs/notes.txt project/docs/design.txt
cat project/docs/notes.backup
cat project/docs/design.txtПосле копирования существуют два независимых файла с одинаковыми байтами. После переименования старого имени notes.txt больше нет, а design.txt содержит прежний текст. Изменение резервной копии не обязано менять рабочий файл. При существующем назначении cp и mv могут перезаписать данные: наличие команды в инструкции не делает её безопасной для любого пути.
Для ручной работы можно выбрать cp -i или mv -i, чтобы получить вопрос при перезаписи. Это помощь человеку, а не надёжная автоматическая проверка состояния: файл может измениться между проверкой и действием. В лаборатории назначение новое. Каталоги копируют с подходящими рекурсивными опциями; не выбирайте cp -r до того, как поняли исходный и конечный путь.
Имя и объект
Каталог связывает имена с объектами файловой системы. Поэтому переименование обычно меняет связь, а не переписывает всё содержимое. Символическая ссылка хранит путь к другому объекту. Она может существовать, даже если цель ещё не появилась или уже удалена.
ln -s design.txt project/docs/latest.txt
ls -l project/docs/latest.txt
cat project/docs/latest.txtЦель design.txt здесь относительна каталогу, где находится ссылка, то есть project/docs. Ссылка не отсчитывает этот путь от любого будущего рабочего каталога читателя. Если переименовать цель, ссылка может стать битой. Hard link связывает другое имя с тем же объектом и имеет иные ограничения; для курса достаточно понимать, что это тоже не независимая копия. Не используйте ссылки как замену backup.
Ищем по дереву
find project -type f -name '*.txt' -print
find project/docs -type l -print
find project -type f -name '*.txt' -exec wc -l {} \;find начинает обход с выбранного каталога. -type f выбирает обычные файлы, -type l — символические ссылки. Кавычки оставляют шаблон для find, а не раскрывают его в shell заранее. -exec передаёт найденный путь аргументом другой программе; {} обозначает это место, экранированная точка с запятой завершает действие find.
Не стройте обработку имён через for f in $(ls ...): пробелы и переводы строк разрушат границы. Если нужен список для другой программы, есть нулевой разделитель -print0 и совместимый приёмник xargs -0. Но для простого запуска над каждым файлом -exec уже сохраняет имена и не требует отдельного списка. Опции GNU и BSD могут различаться; здесь используются базовые операции.
Удаление требует выбранного объекта
Обычный rm удаляет имя без обязательной корзины. Не используйте рекурсивное удаление домашней папки или команды с неопределённой переменной. В учебной папке создайте scratch.txt, проверьте его через ls -l ./scratch.txt, затем удалите только этот файл командой rm -i ./scratch.txt. Программа задаст вопрос; ответ должен соответствовать намерению. Эта практика не требует sudo.
Самостоятельная лаборатория
Сделайте копию design.txt, поменяйте содержимое копии и сравните чтение обоих файлов. Затем переименуйте рабочий файл и покажите, что произошло с latest.txt. Найдите все обычные .txt внутри project, не включая ссылку, и посчитайте строки каждого файла. Объясните, почему порядок выдачи find не следует считать сортировкой.
Критерии готовности: резервная копия независима, ссылка распознаётся, путь с пробелом не распался, поиск ограничен вашим проектом. Удалён только специально созданный scratch. Вы можете воспроизвести результат из заметок после нового входа, указав сохранённый путь лаборатории.
Разбор
Изменённая копия содержит новую строку, оригинал сохраняет прежнюю. После переименования цели относительная ссылка указывает на отсутствующее старое имя; это ожидаемый результат, не повреждение диска. Find печатает найденные пути, а wc считает строки по полученным аргументам. В следующем уроке перейдём от имён файлов к обработке их содержимого.
Первичные источники: GNU Coreutils: cp, Findutils: безопасные имена, Coreutils: symbolic links.