Cmd удалить все файлы кроме последних
Одной из особенностей последних версий Windows 10 является способность поддерживать себя в чистоте, автоматически удаляя ставшие ненужными по истечении определённого срока файлы. В более ранних версиях системы, в которых эта функция ещё не реализована, для удаления старых файлов можно использовать командную строку, консоль PowerShell и даже Проводник, хотя процедура очистки с помощью последнего не так удобна.
Рассмотрим все три варианта.
Удаление старых файлов с помощью Проводника
Лента Проводника Windows 10 и 8.1 содержит инструмент, который позволяет отсортировать все файлы в каталоге по дате изменения, типу, размеру и некоторым другим свойствам. Допустим, вы хотите удалить файлы старше одного месяца. Зайдите в папку с залежавшимися в ней файлам и нажмите на клавиатуре F3 . При этом вы будете переключены в ленте Проводника в раздел поиска.
Кликните по иконке "Дата изменения" и выберите в выпадающем списке нужный период времени, в данном случае месяц.
Удаление старых файлов в командной строке
Для удаления файлов с "истёкшим сроком годности" мы будем использовать консольную утилиту ForFiles.exe , отвечающую за выбор объекта и выполнение с ним указанного действия. Утилита поддерживает несколько параметров, а именно:
• /S — позволяет выполнять рекурсивный поиск.
• /P — указывает путь к разделу или каталогу.
• /D — указывает количество дней с момента последней модификации.
• /C — задаёт команду действия над файлом.
В команде ForFiles также можно указывать возвращающие различные значения переменные, например, @file , которая возвращает имя файла и которую мы будем использовать. Удалим для примера все файлы старше 10 дней в папке "Картинки", лежащей в корне системного диска.
Открываем командную строку и выполняем такую команду:
В примере используются три ключа /p (путь) , /s (рекурсия) и /d (количество дней) , а также команда удаления del и переменная имени файла @file . Как только мы нажмём ввод , ForFiles пробежится по всему содержимому папки "Картинки", включая вложенные каталоги и удалит все файлы старше 10 дней .
Как видите, этот способ более эффективный и быстрый, кроме того, вы можете его автоматизировать, создав для него задания в Планировщике.
Удаление старых файлов с помощью PowerShell
Здесь практически всё то же самое, что и в примере с командной строкой, разве что синтаксис иной. Предположим, что ни путь к папке с файлами, ни цели у нас не изменились. Запускаем консоль PowerShell и выполняем команду такого вида:
Результат будет аналогичным предыдущему.
Обратите внимание, что в команде также используется рекурсия (-Recurse) и указание даты в днях AddDays(-10).
а также все файлы, в имени которых (в том числе и имени папки в пути) содержится aa bb. Поэтому ИМХО, этим надо пользоваться осторожнее.-------
Даже самая сложная проблема обязательно имеет простое, лёгкое для понимания, неправильное решение. Каждое решение плодит новые проблемы.
Конфигурация компьютера | |
Процессор: Intel(R) Core(TM) i3 CPU M 370 2.40GHz, ядер: 2, логических процессоров: 4 | |
Память: 8,00 ГБ | |
ОС: Windows 10 Pro x64 |
тут в данном случае все четко определено и если так же четко подавать (и учесть что не будет таких: ""Ru.pdfEn.pdf""имен файлов, хотя почему и нет), то работать будет, а соломку с собой носить надо
А если этот служебный файл расположить где-то в %tmp%, то потом им в xcopy не воспользуешься. » |
Конфигурация компьютера | |
Процессор: Intel(R) Core(TM) i3 CPU M 370 2.40GHz, ядер: 2, логических процессоров: 4 | |
Память: 8,00 ГБ | |
ОС: Windows 10 Pro x64 |
Iska,
Не работает
xcopy Z:\temp\*.* /L /EXCLUDE:"Z:\У попа была собака\kuku"
xcopy Z:\temp\*.* /L /EXCLUDE:Z:\У попа была собака\kuku
xcopy Z:\temp\*.* /L /EXCLUDE:"kuku"
Работает
xcopy Z:\temp\*.* /L /EXCLUDE:Z:\Траляля\kuku
Еще другая неприятность с ключом L: xcopy Z:\temp\*.* /L работать не будет, если находиться в папке где файлы (Z:\temp\), выдаст "Невозможно скопировать файл в себя".
ИМХО аккуратнее написать, например
xcopy Z:\temp\*.* "%Tmp%\" /L
то есть в качестве выходной указать другую существующую папку, хотя туда и ничего не попадёт. Кстати, еще странность: если там будет файл с таким же именем, как и в исходной папке, выдаст запрос на перезапись.
Извините, впал в глубокий оффтоп, но конструкция
при наличии кириллических символов в названии для xcopy не работает, а Dir - пожалуйста! (хотел записать рез работы xcopy в файл для прочтения в notepad)alpap, а если батник запускается с расшаренного ресурса с запретом на запись?
Вообще, xcopy моя любимая команда, но иногда доводит до истерики
-------
Даже самая сложная проблема обязательно имеет простое, лёгкое для понимания, неправильное решение. Каждое решение плодит новые проблемы.
Феерическая расстановка точек над i в вопросе удаления файлов из переполненной директории.
Прочитал статью Необычное переполнение жесткого диска или как удалить миллионы файлов из одной папки и очень удивился. Неужели в стандартном инструментарии Linux нет простых средств для работы с переполненными директориями и необходимо прибегать к столь низкоуровневым способам, как вызов getdents() напрямую.
Для тех, кто не в курсе проблемы, краткое описание: если вы случайно создали в одной директории огромное количество файлов без иерархии — т.е. от 5 млн файлов, лежащих в одной единственной плоской директории, то быстро удалить их не получится. Кроме того, не все утилиты в linux могут это сделать в принципе — либо будут сильно нагружать процессор/HDD, либо займут очень много памяти.
Так что я выделил время, организовал тестовый полигон и попробовал различные средства, как предложенные в комментариях, так и найденные в различных статьях и свои собственные.
Подготовка
Так как создавать переполненную директорию на своём HDD рабочего компьютера, потом мучиться с её удалением ну никак не хочется, создадим виртуальную ФС в отдельном файле и примонтируем её через loop-устройство. К счастью, в Linux с этим всё просто.
Создаём пустой файл размером 200Гб
Многие советуют использовать для этого утилиту dd, например dd if=/dev/zero of=disk-image bs=1M count=1M , но это работает несравнимо медленнее, а результат, как я понимаю, одинаковый.
Форматируем файл в ext4 и монтируем его как файловую систему
К сожалению, я узнал об опции -N команды mkfs.ext4 уже после экспериментов. Она позволяет увеличить лимит на количество inode на FS, не увеличивая размер файла образа. Но, с другой стороны, стандартные настройки — ближе к реальным условиям.
Создаем множество пустых файлов (будет работать несколько часов)
Кстати, если в начале файлы создавались достаточно быстро, то последующие добавлялись всё медленнее и медленнее, появлялись рандомные паузы, росло использование памяти ядром. Так что хранение большого числа файлов в плоской директории само по себе плохая идея.
Проверяем, что все айноды на ФС исчерпаны.
Размер файла директории
Теперь попробуем удалить эту директорию со всем её содержимым различными способами.
Тесты
После каждого теста сбрасываем кеш файловой системы
sudo sh -c 'sync && echo 1 > /proc/sys/vm/drop_caches'
для того чтобы не занять быстро всю память и сравнивать скорость удаления в одинаковых условиях.
Удаление через rm -r
$ rm -r /mnt/test_dir/
Под strace несколько раз подряд (. ) вызывает getdents() , затем очень много вызывает unlinkat() и так в цикле. Занял 30Мб RAM, не растет.
Удаляет содержимое успешно.
Т.е. удалять переполненные директории с помощью rm -r /путь/до/директории вполне нормально.
Удаление через rm ./*
$ rm /mnt/test_dir/*
Запускает дочерний процесс шелла, который дорос до 600Мб, прибил по ^C . Ничего не удалил.
Очевидно, что glob по звёздочке обрабатывается самим шеллом, накапливается в памяти и передается команде rm после того как считается директория целиком.
Удаление через find -exec
$ find /mnt/test_dir/ -type f -exec rm -v <> \;
Под strace вызывает только getdents() . процесс find вырос до 600Мб, прибил по ^C . Ничего не удалил.
find действует так же, как и * в шелле — сперва строит полный список в памяти.
Удаление через find -delete
$ find /mnt/test_dir/ -type f -delete
Вырос до 600Мб, прибил по ^C . Ничего не удалил.
Аналогично предыдущей команде. И это крайне удивительно! На эту команду я возлагал надежду изначально.
Удаление через ls -f и xargs
$ cd /mnt/test_dir/ ; ls -f . | xargs -n 100 rm
параметр -f говорит, что не нужно сортировать список файлов.
Создает такую иерархию процессов:
Удаление через perl readdir
$ perl -e 'chdir "/mnt/test_dir/" or die; opendir D, "."; while ($n = readdir D) < unlink $n >' (взял здесь)
Под strace один раз вызывает getdents() , потом много раз unlink() и так в цикле. Занял 380Кб памяти, не растет.
Удаляет успешно.
Получается, что использование readdir вполне возможно?
Удаление через программу на C readdir + unlink
$ gcc -o cleandir cleandir.c
$ ./cleandir
Под strace один раз вызывает getdents() , потом много раз unlink() и так в цикле. Занял 128Кб памяти, не растет.
Удаляет успешно.
Опять — же, убеждаемся, что использовать readdir — вполне нормально, если не накапливать результаты в памяти, а удалять файлы сразу.
Иногда надо сделать удаление файлов старше n дней. Например Backup’ ы. Можно делать это вручную, отсортировать их по дате и удалить, а можно воспользоваться скриптом. В данном примере мы рассмотрим скрипт для удаления файлов старше n дней и добавим задание в планировщик Windows Server 2012R2.
Иногда надо сделать удаление файлов старше n дней. Например Backup’ ы. Можно делать это вручную, отсортировать их по дате и удалить, а можно воспользоваться скриптом. В данном примере мы рассмотрим скрипт для удаления файлов старше n дней и добавим задание в планировщик Windows Server 2012R2.
Содержание:
1. Скрипт удаления файлов старше n-дней
2. Создание задания в планировщике задач
Скрипт на самом деле очень простой, создается в PowerShell и выглядит он следующим образом:
Где:
F:\backup\ - путь, в какой папке мы будем с вами искать файлы для удаления *.* - имя (маска) файлов /d -30 - старше скольки дней нам необходимо удалить файлы.
Вот так это выглядит в PowerShell:
Осталось только его выполнить и все.
Все хорошо, у нас есть скрипт. Мы можем выполнять его вручную, когда необходимо очистить наши бекапы. Но зачем выполнять это вручную? Мы поручим планировщику запускать наш скрипт и избавимся сами от рутинной работы.
Итак, что нам для этого надо?
Для начала идем в "Пуск -> панель управления -> Администрирование" и запускаем там "Планировщик заданий".
Выбираем пункт "Создать задачу":
На вкладке "Общие" задаем имя задания, его описание и пользователя, от которого оно будет выполняться. По умолчанию там будет пользователь, под которым вы вошли в данный момент в систему.
Далее переходим на вкладку "Триггеры" и создаем расписание, когда мы будем запускать наше задания. У меня настроено в 10:00 каждые 2 дня.
Далее идем на вкладку "Действия" и задаем действие, которое будет выполняться. Выбираем "Запуск программы"
программу или сценарий
и указываем путь до PowerShell:
А аргументе указываем путь до нашего скрипта, который мы создали ранее:
Нажимаем "Ок" и еще раз "Ок"
Все, на этом наше задание создано. Осталось дождаться, когда будет выполнено наше действие по расписанию и проверить, все ли правильно было настроено.
Читайте также: