Как rm -r выполняет рекурсивное удаление? В каком порядке?

Как rm -r выполняет рекурсивное удаление? В каком порядке?

Есть ли какой-то порядок операций rm? Я выполнил операцию rmв большом каталоге и мне интересно, где мне посмотреть, что могло быть удалено. rmРаботает ли сначала с файлами, а затем с каталогами? Или это основано на какой-то информации в таблице инодов?

Характеристики: rm из GNU coreutils 8.22 Система: Arch Linux, работающая на файловой системе beagleboneblack, работающей на внешнем жестком диске Seagate (ext4) с использованием USB 2.0.

Предыстория:

Я выполнял очистку каталога и выполнил

cp -r A/ B/ C/ Dest/

Невольно я продолжил:

rm -r A/ B/ C/ Dest/

когда я имел в виду просто выступить

rm -r A/ B/ C/

Я поймал это и нажал Ctrl+ C, прежде чем прошло слишком много времени. В частности, это было < 3 секунд, так как я использовал команду timeв сочетании с rm& cp. Я вошел и проверил, Dest/ожидая, что его не будет, но, о чудо, он был целым ипоявилсяне быть затронутыми. Это немного удивительно, так как A/ B/ C/они довольно малы. Может быть, 100–200 МБ в общей сложности. Dest/однако, это чуть меньше 1 ТБ. Выполнение lsна Dest/ показало, что были и файлы, и каталоги на обоих концах алфавита (например AFile.txt.... .... Zoo.txt).

Мне повезло, и я отменил rmдо того, как он нанес ущерб моему каталогу Dest/? rmНеужели так медленно (к счастью!)?

Если нет, то как rmрекурсивно удалить данные, чтобы я мог предположить, что именно было потеряно?

Я на самом деле не рассчитываю вернуть то, что я мог потерять, просто интересно, что именно могло быть утеряно.

решение1

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

Это точно такой же метод, который используют другие приложения для рекурсивного обхода каталогов — find, ls -Rf, и т. д.

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

Обратите внимание, что lsили echo *сортируйте файлы в лексикографическом порядке их имен. findили ls -fне сортируйте.

Единственное, на что можно положиться, это то, что аргументы обрабатываются по порядку. Так что если бы C/он все еще был частично там, это означало бы, что Dest/он нетронут. Если C/он исчез, вы можете получить представление о том, где были удалены файлы, Dest/проверив время изменения каталога и сравнив его со временем C/удаления или временем окончания копирования. Первым файлом, который будет удален, может быть файл, находящийся непосредственно в Dest/иерархии или где-то глубоко в ней, в зависимости от того, была ли первая запись, Dest/которая rmпрошла через каталог, или нет.

Скорость rmв основном зависит от того, сколько файлов нужно удалить. Чтобы заметно повлиять на время удаления, нужен очень большой файл. Основная часть работы — это удаление каждой записи каталога по очереди. Данные файла не стираются, для стирания содержимого файла требуется только пометить блоки, которые он использовал, как свободные, что относительно быстро.

решение2

Как говорит Жиль, в общем случае невозможно предсказать порядок удалений в каталоге, можно лишь предположить, что каталоги верхнего уровня будут обработаны в порядке, указанном в командной строке.

Однако вам также гарантировано, что он удалит иерархии каталогов снизу вверх, поскольку Unix позволяет удалять каталоги только в том случае, если они пусты. Поэтому, чтобы удалить каталог, сначала нужно удалить все в нем. Если он содержит подкаталоги, сначала нужно удалить их содержимое и так далее.

Связанный контент