Как удалить файл или каталог в Linux через терминал: rm, rmdir и безопасные привычки
Разбираем удаление в терминале: rm для файлов, rmdir для пустых каталогов, rm -r для каталогов с содержимым. Отдельно — чем опасен rm -rf, как удалить файл со странным именем, почему после удаления не освободилось место и как настроить автоочистку старых логов.
В Linux нет корзины: удалённое из терминала не восстанавливается штатными средствами. Поэтому важно не просто знать команду, а понимать, что именно она снесёт. Разбираем rm и rmdir, их флаги, приёмы безопасного удаления и решение проблемы «файл удалил, а место не появилось».
Удаляем файл
rm report.txt
Никакого подтверждения и никакого вывода — файл просто исчезает. Несколько файлов сразу:
rm access.log error.log debug.log
Спрашивать подтверждение перед каждым файлом:
rm -i report.txt
# rm: remove regular file 'report.txt'? y
Игнорировать несуществующие файлы и не спрашивать вообще:
rm -f temp.txt
Флаг -f (force) полезен в скриптах: команда не упадёт с ошибкой, если файла уже нет. В интерактивной работе он же делает rm максимально молчаливым, поэтому набирать его по привычке — плохая идея.
Удаляем каталог
Здесь два инструмента, и разница между ними принципиальна.
rmdir удаляет только пустой каталог:
rmdir old_project
Если внутри что-то есть, команда откажется: Directory not empty. Это не ограничение, а страховка — вы точно не потеряете данные.
rm -r удаляет каталог вместе со всем содержимым, рекурсивно:
rm -r old_project
Именно эта команда нужна, когда спрашивают, как удалить директорию в Linux через терминал: в каталоге почти всегда что-то лежит.
Полезный флаг rmdir -p — удалить каталог вместе с опустевшими родительскими:
rmdir -p project/build/tmp
Если после удаления tmp каталог build останется пустым, он тоже удалится, и так вверх по цепочке до первого непустого.
С подтверждением на каждый объект:
rm -ri old_project
Разумный компромисс — -I (заглавная): один вопрос на всю операцию, если файлов больше трёх:
rm -rI old_project
Это заметно удобнее, чем отвечать y сто раз, и всё же оставляет момент, когда можно остановиться.
rm -rf: чем именно опасен
Комбинация означает «рекурсивно, принудительно, без вопросов». Работает мгновенно и без подтверждений. Три классических способа потерять данные:
Пробел не там. Пробел разделяет аргументы, поэтому команда читается не так, как задумано:
rm -rf /home/user /old-backups # два аргумента: снесёт весь /home/user
rm -rf /home/user/old-backups # то, что имелось в виду
Пустая переменная. В скрипте это приводит к катастрофе:
rm -rf "$BACKUP_DIR"/* # если переменная пуста, получится rm -rf /*
Защита — проверка перед удалением или строгий режим:
set -u # обращение к неустановленной переменной = ошибка
[ -n "$BACKUP_DIR" ] || exit 1 # явная проверка
rm -rf "${BACKUP_DIR:?переменная не задана}"/*
Конструкция ${VAR:?текст} прерывает выполнение с сообщением, если переменная пуста или не задана. Для скриптов удаления это самая дешёвая страховка. Про строгий режим и проверки — в статье про условия if/else в bash.
Незакрытая кавычка или неверная маска. Раскрытие * делает шелл, а не rm — команда получает уже готовый список. Поэтому проверяйте, что раскроется, до удаления:
ls *.log # смотрим список
echo rm *.log # видим точную команду
rm *.log # выполняем
Современный rm отказывается удалять корень (--preserve-root включён по умолчанию), но это защищает только от буквального rm -rf /, а не от rm -rf /home или rm -rf /*.
Удаляем по маске и по условию
Все .tmp в текущем каталоге:
rm *.tmp
Рекурсивно по всему дереву — уже задача для find:
find /var/tmp -type f -name "*.tmp" -delete
Разбор по частям: -type f — только файлы (каталоги не тронет), -name "*.tmp" — маска имени, -delete — действие. Кавычки вокруг маски обязательны, иначе её раскроет шелл ещё до запуска find.
Хорошая привычка — сначала посмотреть список, потом добавить -delete:
find /var/tmp -type f -name "*.tmp" # что найдётся
find /var/tmp -type f -name "*.tmp" -delete # удаляем
Файлы старше 30 дней — типовая задача для очистки логов и бэкапов:
find /var/backups -type f -mtime +30 -delete
Пустые каталоги после чистки:
find /var/tmp -type d -empty -delete
Файлы больше гигабайта:
find /var/log -type f -size +1G
Полный разбор поиска, включая -exec и логические операторы, — в руководстве по find. Регулярную очистку удобно повесить задачей cron.
Файлы со странными именами
Имя начинается с дефиса. rm принимает его за флаг:
rm -file.txt # invalid option
rm -- -file.txt # всё после -- считается именами
rm ./-file.txt # либо через явный путь
Пробелы в имени — кавычки или экранирование:
rm "мой файл.txt"
rm мой\ файл.txt
Совсем нечитаемое имя — удаляем по номеру inode. Сначала узнаём номер:
ls -li
# 1573248 -rw-r--r-- 1 user user 0 авг 12 10:00 ?????
find . -maxdepth 1 -inum 1573248 -delete
Имя неизвестно, но каталог мешает — интерактивно перебрать содержимое:
rm -i ./*
Место не освободилось после удаления
Частая ситуация на сервере: удалили гигабайтный лог, а df -h показывает тот же занятый объём. Причина в том, что файл всё ещё открыт процессом. В Linux данные освобождаются, когда исчезает и последняя ссылка из файловой системы, и последний открытый дескриптор.
Найти такие файлы:
sudo lsof +L1
Колонка NLINK со значением 0 означает: файл удалён, но процесс его держит. Решения два — перезапустить сервис:
sudo systemctl restart myapp
или, если перезапуск нежелателен, обнулить файл через дескриптор в /proc:
sudo truncate -s 0 /proc/<PID>/fd/<N>
Отсюда практический вывод: распухший лог правильнее обнулять (> /var/log/app.log), а не удалять — тогда место освобождается сразу и приложение продолжает писать в тот же файл. Проверить, куда ушло место, помогают du -sh * и df -h, а обзор дисков даёт lsblk.
Корзина в терминале
Если хочется обратимости, ставится trash-cli — файлы уезжают в стандартную корзину рабочего стола, а не исчезают:
sudo apt install trash-cli
trash-put report.txt # переместить в корзину
trash-list # посмотреть содержимое
trash-restore # восстановить
trash-empty 30 # очистить старше 30 дней
Соблазнительно сделать alias rm='trash-put', но это опасная привычка: на чужом сервере, где алиаса нет, рука выполнит настоящий rm. Лучше приучить себя к отдельной команде trash-put.
Гарантированное затирание
Обычное удаление не стирает данные — освобождаются лишь блоки, а содержимое остаётся на диске до перезаписи. Для файла с секретами этого мало:
shred -u -z -n 3 secrets.txt
Здесь -n 3 — три прохода перезаписи, -z — финальный проход нулями, -u — удалить файл после затирания.
Важное ограничение: на SSD, а также на файловых системах с копированием при записи (btrfs, ZFS) и на любых журналируемых ФС гарантии нет — контроллер или файловая система могут писать в другие блоки. Надёжный вариант для таких носителей — полное шифрование диска, тогда достаточно уничтожить ключ. Про снапшоты, которые тоже сохраняют «удалённые» данные, — в статье про btrfs.
Права: почему файл не удаляется
Право на удаление файла определяется правами на каталог, а не на сам файл. Достаточно иметь w и x на каталоге — даже если файл принадлежит другому пользователю и открыт только на чтение.
ls -ld /var/www/uploads # права на каталог
ls -l /var/www/uploads/a # права на файл
Отсюда два типичных случая:
Permission denied — нет прав на запись в каталог. Нужен sudo или смена прав, см. chmod и chown.
Operation not permitted при наличии прав — на файле стоит атрибут неизменяемости:
lsattr secrets.conf # ----i---------
sudo chattr -i secrets.conf # снять
rm secrets.conf
Отдельный случай — /tmp: там установлен sticky bit (drwxrwxrwt), поэтому удалять файлы может только их владелец, хотя писать в каталог могут все.
Частые вопросы
Как удалить непустой каталог в Linux?
Командой rm -r имя_каталога — она удаляет каталог вместе со всем содержимым. rmdir для этого не подходит: он работает только с пустыми каталогами и вернёт Directory not empty.
Если хочется контроля, используйте rm -rI — команда задаст один вопрос перед удалением, когда объектов больше трёх.
Чем rmdir отличается от rm -r?
rmdir удаляет только пустой каталог и отказывается работать, если внутри что-то есть. rm -r удаляет рекурсивно всё содержимое без вопросов.
rmdir удобен именно как страховка: если команда прошла, вы точно ничего не потеряли. Для гарантированной очистки дерева нужен rm -r.
Как удалить файл, имя которого начинается с дефиса?
Через двойной дефис — rm -- -file.txt — или через явный путь rm ./-file.txt. Без этого rm попытается разобрать имя как набор флагов и вернёт ошибку.
Правило работает и для других команд: -- означает «дальше аргументы, а не опции».
Почему после удаления файла не освободилось место на диске?
Файл удалён из каталога, но его продолжает держать открытым какой-то процесс, и ядро не освобождает блоки до закрытия дескриптора. Найти виновника: sudo lsof +L1.
Помогает перезапуск процесса. Чтобы ситуация не повторялась, распухшие логи обнуляйте (> file.log), а не удаляйте, — либо настройте logrotate.
Можно ли восстановить файл после rm?
Штатными средствами — нет, корзины в терминале не существует. Шансы есть только при немедленных действиях: размонтировать раздел и пробовать extundelete или testdisk, пока блоки не перезаписаны. На активно работающем сервере это почти безнадёжно.
Практический вывод — заранее: регулярные бэкапы, trash-cli для ручной работы и -I вместо -f в повседневных командах.
Что запомнить
rm файл— файл,rmdir каталог— только пустой каталог,rm -r каталог— каталог с содержимым.rm -rfне задаёт вопросов и не имеет отмены: перед запуском проверяйте команду черезlsилиecho.- В скриптах защищайте переменные:
set -uи${VAR:?}не дадутrm -rf "$DIR"/*превратиться вrm -rf /*. - Массовое удаление по условию — через
findс-delete, обязательно сначала посмотрев список без-delete. - Право на удаление даёт каталог, а не файл; если удаление не идёт при наличии прав — проверьте атрибут
iчерезlsattr.