Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Удаление старых файлов/папок если их кол-во больше n (http://forum.oszone.net/showthread.php?t=263677)

greenOwl 03-07-2013 14:32 2178652

Удаление старых файлов/папок если их кол-во больше n
 
Добрый день!
Помогите со скриптом, который будет сканировать нужную папку (например: C:\aaa), и если в нем файлов больше чем n (например 10), то удалить самый старый файл. И тоже самое нужно для папок.
Очень надеюсь на вашу помощь.

Iska 03-07-2013 15:23 2178677

Цитата:

Цитата greenOwl
то удалить самый старый файл »

Один файл?

Цитата:

Цитата greenOwl
И тоже самое нужно для папок. »

Домашнее задание?

greenOwl 03-07-2013 15:43 2178694

Хотя бы для одного файла, но лучше конечно, столько файлов, что бы осталось n.
Не, не домашка, как у всех, архивирование )

Iska 03-07-2013 16:07 2178713

Файлы:
Код:

@echo off
setlocal enableextensions enabledelayedexpansion

set sFolder=C:\Documents and Settings\User\Мои документы\Мои рисунки\PicPic
set /a iCount = 10

for /f "skip=%iCount% usebackq delims=" %%i in (
        `dir /b /a:-d /o:-d /t:w "%sFolder%"`
) do echo del /f /q "%sFolder%\%%~i"

endlocal
exit /b 0

Если файлы, подлежащие удалению, отображаются верно — уберите «echo» перед «del» для их реального удаления.

greenOwl 03-07-2013 16:29 2178728

Iska, спасибо огромное, а то я искал, не нашел, думал, что на этом и остановлюсь :laiel:

Freddy1984 06-07-2018 10:36 2820826

Iska, а для папок не подскажете как?

Iska 06-07-2018 13:47 2820844

Цитата:

Цитата Freddy1984
Iska, а для папок не подскажете как? »

Примерно так:
Код:

@echo off
setlocal enableextensions enabledelayedexpansion

set sFolder=C:\Documents and Settings\User\Мои документы\Мои рисунки\PicPic
set /a iCount = 10

for /f "skip=%iCount% usebackq delims=" %%i in (
        `dir /b /a:d /o:-d /t:w "%sFolder%"`
) do echo rd /s /q "%sFolder%\%%~i"

endlocal
exit /b 0

Будьте крайне осторожны! Не проверялось! Если каталоги, подлежащие удалению, отображаются верно — уберите «echo» перед «rd» для их реального удаления.

KaПaTы4 09-04-2019 10:35 2867156

Приветствую. Подскажи, как написать bat файл и сделать его приложением. Что бы в нем можно было выбирать сетевые или просто пути для разделов в которых хранятся файлы и папки, и для каждого раздела можно было бы указывать какое количество файлов допустимо в данном разделе и какой объем памяти должен быть для данного раздела, если он превышается что бы программа удаляла старые архивы файлы или папки. Пример для 1С бухгалтерии выделен раздел 1 ТБ но он вечно заполняется и уследить не успеваю, так чтобы при его критичном заполнении удалялись старые резервные копии, либо при превышении n-го количества фалов в разделе удалялись старые. За ранее большое спасибо.

alpap 09-04-2019 13:12 2867170

Цитата:

Цитата KaПaTы4
сделать его приложением »

найдите "Bat_To_Exe_Converter", например.
Цитата:

Цитата KaПaTы4
выбирать сетевые или просто пути для разделов »

Цитата:

Цитата KaПaTы4
указывать какое количество файлов »

поставьте в переменных параметры
set "sFolder=%~1"
set /a iCount =%~2
и запускайте так: "name.bat" "Диск:\Папка" "Число файлов"

KaПaTы4 10-04-2019 06:42 2867253

Извините за режим чайника. Немного не въехал(((
set "sFolder=%~1"
set /a iCount =%~2
что выполняют данные п

Iska 10-04-2019 07:04 2867257

Цитата:

Цитата KaПaTы4
что выполняют данные п »

Пытаются присвоить переданные пакетному файлу параметры двум переменным окружения.

alpap 12-04-2019 14:50 2867559

KaПaTы4,
ну что непонятного?
Берем код Iska из поста 4, подставляем параметры в значения переменных так:
Код:

@echo off
setlocal enableextensions enabledelayedexpansion

set "sFolder=%~1"
set /a "iCount=%~2"

for /f "skip=%iCount% usebackq delims=" %%i in (
        `dir /b /a:-d /o:-d /t:w "%sFolder%"`
) do echo del /f /q "%sFolder%\%%~i"

endlocal
exit /b 0

и запускаем как я указал в посте 9 так:
Код:

name.bat "Диск:\Папка" "Число файлов"

POV 10-01-2023 12:51 3000625

Доброе время суток !
Прошу помощи .... 3 дня копания на различных ресурсах не дали результат :-(
По поводу удаления старых файлов: Есть файловая помойка на удаленном компе \\fs\obmen
Если делать типа так

@echo off
SET Path2Del=\\fs\Obmen\
forfiles -p "%Path2Del%" -s -m *.* -d -10 -c "cmd /c del /q @path"
for /f %%D in ('DIR cd "%Path2Del%" /AD/B ^| sort /r') do RD "%%D"

всё отлично отрабатывается и файлы старше 10 дней уничтожаются. Но проблема в том, что в папки сотрудники кидают и файлы которым сто лет в обед, и соответственно скрипт видит, что они старые и на следующий день их кикает ( потому как они не ВНОВЬ созданные )
Внимание, вопрос к знатокам: Каким образом можно либо автоматически переделывать у данных файлов дату на момент появления в директориях ( я уже думал, может перед выполнением скрипта бэкапить новые "старые" файлы, удалять их, а потом заново заливать, но со свежей датой) , либо каким-то образом переделать скрипт.

Пожалуйста помогите. Задача архиважная.
Заранее СПАСИБО.

YuS_2 10-01-2023 15:15 3000631

Цитата:

Цитата POV
проблема в том, что в папки сотрудники кидают и файлы которым сто лет в обед, и соответственно скрипт видит, что они старые и на следующий день их кикает ( потому как они не ВНОВЬ созданные ) »

Используйте дату создания (при копировании файлов, присваивается текущее время) для отбора файлов на удаление, вместо даты изменения (при копировании файлов не изменяется).
Код:

DIR /?
- поможет в выборе поля даты создания файлов, хотя у Вас для отбора и удаления файлов используется forfiles...
Цитата:

Цитата POV
либо каким-то образом переделать скрипт.
Пожалуйста помогите. Задача архиважная. »

Если только на powershell... либо подождите megaloman, возможно, он что-нибудь придумает на cmd...

DJ Mogarych 10-01-2023 16:08 3000633

POV, они вновь созданные. Просто forfiles смотрит не на дату создания, а на дату изменения.
Люди кладут файлы, и у файлов новая дата создания, но старая дата изменения.

Возьмём пример:
Код:

dir D:\temp\obmen |select name,creationtime,lastwritetime

Name        CreationTime        LastWriteTime     
----        ------------        -------------     
new-new.txt 10.01.2023 15:56:30 10.01.2023 15:55:11
new-old.txt 10.01.2023 15:55:55 27.12.2022 15:55:11
old-new.txt 27.12.2022 15:55:11 10.01.2023 15:55:11
old-old.txt 27.12.2022 15:55:53 27.12.2022 15:55:53

В вашем случае выбираются файлы со старой датой изменения
Код:

# CMD
forfiles -p "D:\temp\obmen" -s -m *.* -d -10

"new-old.txt"
"old-old.txt"

# Аналог на Powershell
dir D:\temp\obmen |? lastwritetime -lt (get-date).Date.AddDays(-10)

    Каталог: D:\temp\obmen

Mode                LastWriteTime        Length Name                                                                                                                   
----                -------------        ------ ----                                                                                                                   
-a----        27.12.2022    15:55              0 new-old.txt                                                                                                             
-a----        27.12.2022    15:55              0 old-old.txt

Если учитывать дату создания, то будет так (powershell):
Код:

dir D:\temp\obmen |? creationtime -lt (get-date).Date.AddDays(-10)

    Каталог: D:\temp\obmen

Mode                LastWriteTime        Length Name                                                                                                                   
----                -------------        ------ ----                                                                                                                   
-a----        10.01.2023    15:55              0 old-new.txt                                                                                                             
-a----        27.12.2022    15:55              0 old-old.txt

По идее, можно учитывать и обе даты, т. е., удаляться будет только то, что старше 10 дней в обоих случаях (powershell):
Код:

$olderThan = (get-date).Date.AddDays(-10)
dir D:\temp\obmen |? {$_.creationtime -lt $olderThan -and $_.lastwritetime -lt $olderThan} |del -WhatIf
WhatIf: Выполнение операции "Удаление файла" над целевым объектом "D:\temp\obmen\old-old.txt".


POV 11-01-2023 05:14 3000651

Спасибо, дорогие, что откликнулись !
YuS_2,
Цитата:

Цитата YuS_2
Если только на powershell... »

Да по-фигу на чём, лишь-бы работало. Но к сожалению на PowerShell не умею .... Экспериментировал с
HTML код:

https://github.com/sanglyb/remove-old-files-powershell
, но там так-же работает, как и вариант с forfiles. Вот бы кто впихнул в этот .ps1 то, что нужно и куда нужно .... :unsure:
DJ Mogarych
Благодарю, смысл уловил, но опять-же как пониманию на cmd этого в данном случае не реализовать, и опять-же powershell ... (читай выше) ....

YuS_2 11-01-2023 08:09 3000656

Цитата:

Цитата POV
Но к сожалению на PowerShell не умею »

Всё просто: чтобы работать с чем-либо, необходимо прежде изучить таки это самое что-либо :)
Для начала:
https://learn.microsoft.com/ru-ru/po...powershell-7.3
ну и:
https://andpop.ru/courses/winscript/...posh_popov.pdf

а по-быстрому:
1. Проверить политику запуска скриптов (в первой ссылке есть описание, вот более конкретная ссылка). Если стоит запрет на выполнение скриптов, то измените политику выполнения PowerShell на удаленно подписанную.
2. Скрипт лучше оформить в текстовом файле с кодировкой UTF-8 и дать ему какое-либо название, например: script.ps1
3. Запустите скрипт из командной оболочки powershell:
Код:

.\script.ps1
или создайте "батник", со строкой запуска скрипта через powershell:
Код:

@echo off
powershell -ex bypass -f ".\script.ps1"
pause

положите его рядом со скриптом и запустите.


Главное:
Прежде, чем запускать скрипт, откорректируйте его под свои параметры, например так:
Код:

$folder = '\\fs\Obmen\'
$olderThan = (get-date).Date.AddDays(-10)
dir $folder -file |? {$_.creationtime -lt $olderThan -and $_.lastwritetime -lt $olderThan} |del -WhatIf

Посмотрите вывод скрипта... если перечислены правильные файлы на удаление, то уберите параметр -WhatIf в командлете del (сам командлет имеет другое полное название, это его алиас) и выполните скрипт повторно для реального удаления файлов...

POV 11-01-2023 09:20 3000664

YuS_2, Благодарю за ответ.
Про powershell: Естественно я могу такие скрипты запускать, я не умею на них писАть ! Потому и ковырял батники (что проще)
Приведенный Вами вариант смогу испробовать через часик. Дам знать.

POV 11-01-2023 09:52 3000666

Попробовал ....
.ps1 просто схлопывается через секунду, а если через cmd, то "Для продолжения нажмите любую клавишу . . ." и после нажатия такая-же ситуация .... И пробовал запускать под админом.

megaloman 11-01-2023 11:49 3000673

Цитата:

Цитата YuS_2
либо подождите megaloman, возможно, он что-нибудь придумает на cmd.. »

Коллега меня мамонтом обозвал!!! :lol:
Код:

@Echo Off
cls
        Set "BoxIn=\\fs\obmen"
        Set /A Delta=-10
        Call :FromDate %Delta% %Date% "YYYYDDMM"

        Pushd "%BoxIn%"||(Echo Folder %BoxIn% not found &Pause &Exit /B)
                FOR /F "usebackq tokens=1,2,3,5* delims=. " %%i In (`2^>nul Dir /O:-D /T:C^|findstr /R /C:"^..\...\.....  ..:..        .*"`) DO (
                        If %%k%%j%%i LSS %YYYYDDMM% (Echo %%k%%j%%i = "%%m" &Del "%%m")
                )
        Popd
pause
Exit /B 0

:FromDate

rem Пересчет даты на заданное кол-во дней
rem В первом аргументе +- дни
rem Во втором аргументе дата в формате dd.mm.yyyy
rem В третем аргументе имя переменной в кавычках где получим новую дату в формате yyyymmdd

rem Заимствовано http://forum.oszone.net/thread-186889.html
rem вызов Call :FromNow %DeltaDay% %Date% "yyyymmdd"
rem результат в перемменной %yyyymmdd%

 SetLocal
 Set "DT=%~2"
 Set yyyy=%DT:~-4%& set /a mm=100%DT:~3,2%%%100& set /a dd=100%DT:~,2%%%100
 Set /A JD=%~1+dd-32075+1461*(yyyy+4800+(mm-14)/12)/4+367*(mm-2-(mm-14)/12*12)/12-3*((yyyy+4900+(mm-14)/12)/100)/4
 Set /A L=JD+68569,N=4*L/146097,L=L-(146097*N+3)/4,I=4000*(L+1)/1461001
 Set /A L=L-1461*I/4+31,J=80*L/2447,K=L-2447*J/80,L=J/11
 Set /A J=J+2-12*L,I=100*(N-49)+I+L
 Set /A yyyy=I,mm=100+J,dd=100+K
 EndLocal& Set "%~3=%yyyy%%mm:~-2%%dd:~-2%"
Exit /B 0

Подразумевается, что формат отображения даты-времени в системе "ДД.ММ.ГГГГ чч:мм"
Проверьте, что у Вас отображается в команде Dir
Для отладки, чтобы скрипт реально не удалял файлы, перед Del можно поставить Echo
&Echo Del "%%m"

YuS_2 11-01-2023 12:51 3000681

Цитата:

Цитата POV
.ps1 просто схлопывается через секунду, а если через cmd, то "Для продолжения нажмите любую клавишу . . ." и после нажатия такая-же ситуация .... И пробовал запускать под админом. »

Тогда откройте консоль powershell и отдельно каждую строку в консоли запускайте, а после возникновения исключения сделайте скриншот и приложите сюда к сообщению...

Цитата:

Цитата megaloman
Коллега меня мамонтом обозвал!!! »

Да прям уж так мамонтом... :)
Совсем нет. Просто на cmd не практикую уже, ибо powershell хватает... а без практики, надо читать мануалы, составлять зубодробильный код, потом проверять всё, что получилось... нет, проще на powershell, всё же... :)

POV 11-01-2023 12:59 3000682

megaloman, чего-то толи я тупой, толи лыжи не едут ....
Подставил в переменные даты 2023 год 09 января и всё равно не удаляются файлы ....
Знаю, что уже надоел :sorry:
Может всё таки попробовать с .ps1 ?
Вот такой вариант хорошо справляется с задачей, но в нём надо подкорректировать , чтобы как я и писал ранее, не удалялись закинутые в данный Obmen старинные файлы.

Код:

$Now = Get-Date
#количество дней, файлы старше которых должны быть удалены
$Days = "10"
#путь до отчищаемой папки
$TargetFolder = "\\FS\Obmen\"
#желаемые расширения файлов
$Extension = "*"
#находим все файлы, которые подходят под наши критерии. А также сортируем список, что бы всё шло от большего пути к меньшему
$LastWrite = $Now.AddDays(-$Days)
$Files = Get-Childitem $TargetFolder -Include $Extension -Recurse | Where{$_.CreationTime -le "$LastWrite" -and $_.LastWriteTime -le "$LastWrite"} | Sort-Object -Descending {$_.FullName.Split('\').Count},FullName
foreach ($File in $Files)
{
 if ($File -ne $NULL -and !$File.PSIsContainer)
 {
  write-host "Deleting File $File" -ForegroundColor "Magenta"
  Remove-Item $File.FullName -Force | out-null
 }
 #Собственно, удаляем файл
 elseif ($File -ne $NULL -and $File.PSIsContainer)
 {
                $FolderInfo = get-Childitem $File.FullName | Measure-Object
                if ($folderInfo.count -eq 0)
                {
                        write-host "Deleting directory - $File" -foregroundcolor "green"
                        Remove-Item $File.FullName -Force | out-null
                }
 }
 else
 {
  Write-Host "No more files to delete!" -foregroundcolor "Green"
 }
 }


POV 11-01-2023 13:16 3000684

Вложений: 2
YuS_2,
Цитата:

Цитата YuS_2
сделайте скриншот и приложите сюда к сообщению... »


YuS_2 11-01-2023 13:57 3000691

POV, т.е. никакого исключения нет, хотя это очень странно... не вижу в первой строке кавычек... а без них никуда. :)
Кроме того, возможно, файлы, которые присутствуют в каталоге, не подходят под условие на удаление. Какая у них дата создания? (можно посмотреть в свойствах файла)
Для проверки, покажите вывод команд:

Код:

$folder = 'D:\TEST\'
dir $folder -file|select name,creationtime,lastwritetime

И про кавычки не забудьте...

YuS_2 11-01-2023 14:15 3000693

POV, а, да... на скриншоте видно, что Вы весь пакет строк пытались запустить за один раз... но надо построчно именно, т.е. каждую строку вставляем, Enter и т.д. ...

DJ Mogarych 11-01-2023 14:31 3000698

Да можно и пакет, просто кавычек не было, поэтому шелл думал, что это продолжение одной строки.

megaloman 11-01-2023 14:31 3000699

Цитата:

Цитата POV
Подставил в переменные даты 2023 год 09 января и всё равно не удаляются файлы .... »

1.Покажите код, где Вы это проделали. Я не предусматривал в своём коде такую манипуляцию.
2. В командной строке запустите Dir \\fs\obmen\*.* >C:\obmen.txt
Хотя бы небольшой кусок получившегося файла приложите к сообщению.

YuS_2 11-01-2023 14:42 3000700

Цитата:

Цитата DJ Mogarych
Да можно и пакет »

Да, конечно, но пакетом, как раз, не всегда можно определить место исключения ... тут ведь, непонятная ситуация, поэтому и предложил построчно, в целях дебага уточнить место затыка...

DJ Mogarych 11-01-2023 16:01 3000713

На первом скрине вторая строка начинается с >>, соответственно, первая не закончилась.

YuS_2 11-01-2023 17:42 3000730

Цитата:

Цитата DJ Mogarych
На первом скрине вторая строка начинается с >>, соответственно, первая не закончилась. »

В этом и дело... исключения нет, проблема не решена... просто лишняя переписка на форуме. А если запустить первую строку отдельно, всё будет понятно, ибо вывалится исключение с описанием проблемы... хотя, сейчас попробовал в пакете без кавычек, исключение всё равно выдается... странно, как у POV, так получилось... ладно, придет - расскажет...

POV 13-01-2023 12:18 3000861

Здравствуйте ещё раз все !
Прошу прощения - были форс мажорные обстоятельства ... :sorry: Не до скриптов было
С батником, увы, так и не заработало :unsure:
Итак: Действительно вот такой вариант РАБОТАЕТ !!! Удаляет файлы через n-дней только ПО ВРЕМЕНИ СОЗДАНИЯ в данной директории, не обращая внимания на дату изменения.
Код:

$Now = Get-Date
$Days = "10"
$TargetFolder = "\\srv-zavod\Obmen\"
$Extension = "*"
$LastWrite = $Now.AddDays(-$Days)
$Files = Get-Childitem $TargetFolder -Include $Extension -Recurse | Where{$_.CreationTime -le "$LastWrite" -and $_.LastWriteTime -le "$LastWrite"} | Sort-Object -Descending {$_.FullName.Split('\').Count},FullName
foreach ($File in $Files)
{
 if ($File -ne $NULL -and !$File.PSIsContainer)
 {
  write-host "Deleting File $File" -ForegroundColor "Magenta"
  Remove-Item $File.FullName -Force | out-null
 }
 elseif ($File -ne $NULL -and $File.PSIsContainer)
 {
                $FolderInfo = get-Childitem $File.FullName | Measure-Object
                if ($folderInfo.count -eq 0)
                {
                        write-host "Deleting directory - $File" -foregroundcolor "green"
                        Remove-Item $File.FullName -Force | out-null
                }
 }
 else
 {
  Write-Host "No more files to delete!" -foregroundcolor "Green"
 }
 }

Теперь остался ,надеюсь, последний вопрос: Какие строки добавить в этот .ps1 и куда, чтобы НЕ УДАЛЯЛИСЬ ИМЕННО СОЗДАННЫЕ ПАПКИ (чтобы сотрудникам заново не приходилось их создавать) или ПРОПИСЫВАТЬ ПАПКИ-ИСКЛЮЧЕНИЯ (что менее удобно)
Заранее благодарю за отзывчивость
P.S.
Вот бы лог куда-нить бы сливался ещё по удаленным файлам ...

YuS_2 13-01-2023 13:09 3000867

Цитата:

Цитата POV
Удаляет файлы через n-дней только ПО ВРЕМЕНИ СОЗДАНИЯ в данной директории, не обращая внимания на дату изменения. »

Не знаю, где Вы взяли этот скрипт, здесь Вам показывали другой... :)
Тем не менее, он таки учитывает обе даты... в нем будут удалятся и файлы, и каталоги по дате создания и дате изменения старше $Days дней.

Цитата:

Цитата POV
Какие строки добавить в этот .ps1 и куда, чтобы НЕ УДАЛЯЛИСЬ ИМЕННО СОЗДАННЫЕ ПАПКИ (чтобы сотрудникам заново не приходилось их создавать) »

Всё тот же скрипт, предложенный DJ Mogarych, с корректировкой для лог-файла (будет перезаписываться при каждом запуске скрипта):
Код:

$folder = 'D:\Test\'
$fout = '.\log_delete.txt'
$n = 10
$olderThan = (get-date).Date.AddDays(-$n)
dir $folder -file -rec -force|? {$_.creationtime -lt $olderThan -and $_.lastwritetime -lt $olderThan}|
tee $fout|del -force -WhatIf


POV 13-01-2023 13:29 3000871

YuS_2
СПАСИБО ОГРОМНОЕ !!!!!! :yahoo:
Куда высылать пиво ? :up
Но для теста поставил 1 день и скрипт НЕ УДАЛЯЕТ файлы, а только констатирует. И кстати лог тоже не появляется
Код:

PS C:\Users\it>> $folder = 'D:\Test\'
$fout = '.\log_delete.txt'
$n = 1
$olderThan = (get-date).Date.AddDays(-$n)
dir $folder -file -rec -force|? {$_.creationtime -lt $olderThan -and $_.lastwritetime -lt $olderThan}|
tee $fout|del -force -WhatIf
WhatIf: Выполнение операции "Удаление файла" над целевым объектом "D:\Test\batnik.bat".
WhatIf: Выполнение операции "Удаление файла" над целевым объектом "D:\Test\README.md".


YuS_2 13-01-2023 13:34 3000874

Цитата:

Цитата POV
Куда высылать пиво ? »

На почту "до востребования"... :)
С наступающим СНГ!

YuS_2 13-01-2023 14:24 3000881

Цитата:

Цитата POV
Но для теста поставил 1 день и скрипт НЕ УДАЛЯЕТ файлы, а только констатирует. И кстати лог тоже не появляется »

Потому, что файлы не подходят по критериям отбора...
1. Если ставить 1 день, то дата создания И дата изменения файла должна быть старее вчерашней даты.
2. Лог не появляется потому, что нет списка файлов.
3. Хмм, что значит констатирует? Если таки файлы отбор проходят, то:
Цитата:

Цитата YuS_2
Посмотрите вывод скрипта... если перечислены правильные файлы на удаление, то уберите параметр -WhatIf в командлете del (сам командлет имеет другое полное название, это его алиас) и выполните скрипт повторно для реального удаления файлов... »

И по логу: если запускаете командлеты в консоли, то лучше укажите абсолютный путь для лог-файла, ибо создаваться в таком виде он будет в текущем каталоге... либо рядом со скриптом, если запускаете именно скрипт

POV 14-01-2023 08:34 3000936

YuS_2,
Цитата:

Цитата YuS_2
то уберите параметр -WhatIf в командлете del »

Да, так всё сработало !!! :yahoo:
И лог тоже появился!
Ещё раз ВСЕМ ОГРОМНОЕ СПАСИБО !!!


Время: 14:05.

Время: 14:05.
© OSzone.net 2001-