rm
Удаление файлов и каталогов — без корзины и без возврата
rm удаляет имена файлов. Корзины нет: удалённое не восстановить. Данные освобождаются, когда исчезает последнее имя (жёсткая ссылка) и файл никем не открыт. Для пустых каталогов есть rmdir. В песочнице — GNU coreutils 9.4.
Синтаксис
rm [опции] файл…
rm -r [опции] каталог…
rmdir [опции] пустой_каталог…
Код возврата: 0 — всё удалено, 1 — что-то не получилось (нет файла, нет прав, каталог без -r).
Опции rm
| Опция | Что делает |
|---|---|
-r, -R | удалять каталоги вместе со всем содержимым |
-d | удалять пустые каталоги (как rmdir) |
-f | не спрашивать и не ругаться на несуществующие файлы; код возврата 0 |
-i | спрашивать про каждый файл |
-I | спросить один раз, если файлов больше трёх или есть -r; мягкая страховка от rm * |
--interactive=never|once|always | то же длинно: never ≈ без вопросов, once = -I, always = -i |
-v | печатать каждое удаление: removed 'd/f', removed directory 'd' |
--one-file-system | при -r не заходить в другие смонтированные ФС |
--preserve-root | отказаться удалять / (включено по умолчанию) |
-- | конец опций: всё дальше — имена файлов |
Из -f, -i, -I действует последняя указанная.
Опции rmdir
| Опция | Что делает |
|---|---|
-p | удалить каталог и затем его пустых родителей: rmdir -p a/b/c удалит c, b, a |
-v | печатать каждое удаление |
--ignore-fail-on-non-empty | молча пропускать непустые каталоги |
rmdir удаляет только пустые каталоги — это и есть его плюс: случайно снести данные им нельзя.
Когда rm спрашивает сам
Без -i rm задаёт вопрос remove write-protected regular file?, только если:
- у файла нет права записи для тебя (root на такие вопросы не нарывается — ему писать можно всегда),
- и стандартный ввод — терминал. В скрипте и в конвейере вопроса нет, файл удаляется.
Права на сам файл для удаления не важны: нужны права записи и входа (w и x) на каталог, в котором он лежит. В каталоге со sticky-битом (/tmp) чужие файлы удалить нельзя.
Примеры
# удалить файл
rm old.log
# каталог со всем содержимым, с отчётом
rm -rv build/
# без ошибки, если файла нет (удобно в скриптах)
rm -f /tmp/app.lock
# один вопрос перед массовым удалением
rm -I *.tmp
# удалить файл с именем, начинающимся с дефиса
rm -- -file.txt
rm ./-file.txt
# пустой каталог и пустых родителей
rmdir -p cache/2024/01
# все .bak в дереве — безопасно для имён с пробелами
find . -name '*.bak' -type f -delete
find . -name '*.bak' -print0 | xargs -0 rm -f --
# сначала посмотри, что попадёт под шаблон
echo rm -r /srv/app/releases/old-*
Подводные камни
- Корзины нет. Перед
rm -rfс переменной или шаблоном сначала выполни то же сechoилиls. - Пустая переменная.
rm -rf "$DIR/"*при пустом$DIRпревращается вrm -rf /*. Защита:rm -rf "${DIR:?не задан}"/*— при пустой переменной оболочка остановится с ошибкой. - Имя с дефиса:
rm -x→ «invalid option -- 'x'». Пишиrm -- -xилиrm ./-x. rm -fскрывает опечатки: несуществующий путь не даст ни ошибки, ни ненулевого кода возврата.- Пробел в пути:
rm -rf /srv/app /oldудалит два каталога —/srv/appи/old. Пути с переменными бери в кавычки. - Место не освобождается, если файл держит открытым процесс: имя исчезло, данные остаются до закрытия. Такие файлы видно в
/proc/*/fdкак(deleted). Для живых логов вместоrmиспользуйtruncate -s 0. rm -rf /без--no-preserve-rootоткажется работать, а вотrm -rf /*— нет: шаблон раскроет оболочка.rm -r .иrm -r ..запрещены: «refusing to remove '.' or '..' directory».