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

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

Bullet-Avalon 14-09-2010 13:32 1495086

Bat ограничивающий кол-во хранимых каталогов.
 
Добрый день, итак расскажу по подробнее, что именно хочу сделать и , что не получается.

Данный скрипт, выполняется каждый день и должен
1. На win2008 делать SystemStateBackup на локальный диск (D)
2. Проверять кол-во бэкапов в указанной папке, на локальном компе (не более 1-го). Путь выглядит так - D:\WindowsImageBackup\server\SystemStateBackup в которой находятся папки с датой, которая соответствует дате бэкапа. Если там находится более 1 бэкапа, то удалить старые бэкапы(папки и их содержимое), оставив тока самый свежий.
3. Проверить папку для бэкапов на удаленной шаре, ограничение на кол-во бэкапов не более 5, опять таки если более -удалить наиболее старые.
4.Копировать с локального хранилища бэкап (пункт2) на удаленную шару(пункт3)

Проблема в следующем, когда скрипт находит что папок больше указанного кол-ва, он пытается их удалить, НО выводит потом сообщение - "ПАПКА НЕ ПУСТА", тоесть для теста создал неск пустых папок, он их удалил норм, а если там уже чтото содержится то выводит данное сообщение. Прошу вас помочь найти и исправить ошибку.

Итак вот сам код
Код:

@echo off
::Первая часть скрипта - SystemStateBackup
rem run the backup echo Backing up systemstate to Local Disk D 
wbadmin start systemstatebackup -backuptarget:d: -quiet 



::Вторая часть скрипта - Проверка кол-ва бэкапов на локальном диске
@Echo Off
SetLocal EnableDelayedExpansion
:: Папка с бэкапами, макс кол-во бэкапов
Set $DST=D:\WindowsImageBackup\server\SystemStateBackup
Set $OLD=1
:: Находим текущие день/месяц/год
For /F "Tokens=1 Delims=." %%i In ('WMIC OS Get LocalDateTime^|Find "."')
Do Set $Time=%%i
Set $Y=%$Time:~0,4%&Set $M=0%$Time:~4,2%&Set $D=0%$Time:~6,2%
Set $M=%$M:~-2%&Set $D=%$D:~-2%
:: Ограничиваем количество архивов
For /F "Tokens=1-3 Delims=." %%i In ('DIR /B/A:D %$DST%\??.??.????')
Do Set $_%%k%%j%%i=%%i.%%j.%%k
For /F "Tokens=2 Delims==" %%i In ('Set $_^|Sort /R') Do (
  Set /A $OLD-=1
  If !$OLD! LSS 0 RD /S/Q "%$DST%\%%i"
)


::Третья часть скрипта - Проверка кол-ва бэкапов на удаленной шаре
@Echo Off
SetLocal EnableDelayedExpansion
:: Папка с бэкапами, макс кол-во бэкапов
Set $DST=\\192.168.0.5\backup$\SystemStateDc
Set $OLD=4
:: Находим текущие день/месяц/год
For /F "Tokens=1 Delims=." %%i In ('WMIC OS Get LocalDateTime^|Find "."')
Do Set $Time=%%i
Set $Y=%$Time:~0,4%&Set $M=0%$Time:~4,2%&Set $D=0%$Time:~6,2%
Set $M=%$M:~-2%&Set $D=%$D:~-2%
:: Ограничиваем количество архивов
For /F "Tokens=1-3 Delims=." %%i In ('DIR /B/A:D %$DST%\??.??.????')
Do Set $_%%k%%j%%i=%%i.%%j.%%k
For /F "Tokens=2 Delims==" %%i In ('Set $_^|Sort /R') Do (
  Set /A $OLD-=1
  If !$OLD! LSS 0 RD /S/Q "%$DST%\%%i"
)


:: Четвертая часть скрипта - копирование с локальной папки на удаленную шару
Set InDir="D:\WindowsImageBackup\server\SystemStateBackup "
Set Double1="\\192.168.0.5\backup$\SystemStateDc"
 rem Set DT=%Date%
Set DT=%Date:~6,4%%Date:~3,2%%Date:~0,2%
Call :CopyDir %InDir% %Double1%
GoTo End
:CopyDir
Set Otkuda="%~1\*.*"
Set Kuda1=%~1
Set Kuda1="%~2\%DT%_%Kuda1:~3,1000%\"
xcopy %Otkuda% %Kuda1% /Y /S
:End


amel27 15-09-2010 04:18 1495596

Цитата:

Цитата Bullet-Avalon
Проблема в следующем, когда скрипт находит что папок больше указанного кол-ва, он пытается их удалить, НО выводит потом сообщение - "ПАПКА НЕ ПУСТА", тоесть для теста создал неск пустых папок, он их удалил норм, а если там уже чтото содержится то выводит данное сообщение. »

не похоже чтобы скрипт, поищите по форуму по фразе "папка не пуста", например:
Ошибка - [решено] Не удается удалить [название папки]. Папка не пуста.

megaloman 15-09-2010 19:15 1496083

Как-то сложновато у Вас ... Вроде бы для разных папок делается одно и то же действие, а Вы зачем-то пишите два куска для этого. Вот батник, который заменяет Ваши вторую и третью части скрипта: работает одна и та же подпрограмма LimCountDir. В ней сначала подсчитываем число папок, затем сколько папок надо удалить, затем по порядочку удаляем их, начиная с самых старых.
Процедура в указанной папке (Where) оставляет указанное кол-во самых свежих подпапок (HowMuch).
для сортировки по датам используется ключ /O команды Dir
С Вашим копированием не разбирался, если бы Вы просто описали, по какому принципу образуются имена файлов (директорий) - было бы проще.
Код:

@Echo off
rem Пути указываем без кавычек и без \ и пробелов на конце
rem -------------------------------------------

Set HowMuch=1
Set Where=F:\Delete\Install
rem ---------------------------------------------------
Call :LimCountDir "%Where%" %HowMuch%
rem ---------------------------------------------------

Set HowMuch=5
Set Where=\\SERVER_NT\{Общая}\Delete\Install
rem ---------------------------------------------------
Call :LimCountDir "%Where%" %HowMuch%
rem ---------------------------------------------------
GoTo :Eof

rem ----------------------------------------------------
:LimCountDir

rem Подсчитаем кол-во директорий (Count) в указанной папке %1 (Путь передали в аргументе)
Set Count=0
FOR /F "usebackq  delims=" %%i IN (`Dir /B /A:D /O:D "%~1\"`) DO Call :CountDir

rem Удалим старые директории в указанной папке %1 сверх максимального количества %2 (передали в аргументе)
Set /A DelCount=%Count%-%2
Set Count=0
FOR /F "usebackq delims=" %%i IN (`Dir /B /A:D /O:D "%~1\"`) DO Call :DelNumCount %DelCount% "%~1\%%i"
GoTo :Eof

:CountDir
Set /A Count=%Count%+1 
GoTo :Eof

:DelNumCount
Set /A Count=%Count%+1
If %Count% LEQ %1 Rd %2 /S /Q
GoTo :Eof
rem ----------------------------------------------------


kiripanda 16-09-2010 00:30 1496324

Цитата:

Цитата megaloman
сначала подсчитываем число папок, затем сколько папок надо удалить... »

а на пуркуа считать?
Код:

FOR /F "usebackq skip=%2 delims=" %%i IN (`Dir /B /A:D /O:-D "%~1\"`) DO RD /S/Q "%~1\%%i"
skip=%2 — сколько папок оставить

megaloman 16-09-2010 10:00 1496510

Цитата:

Цитата kiripanda
FOR /F "usebackq skip=%2 delims=" %%i IN (`Dir /B /A:D /O:D "%~1\"`) DO RD /S/Q "%~1\%%i"

Так Вы оставите самые старые папки. Спасибо, заставили внимательнее прочесть хелп Dir
Цитата:

/O Сортировка списка отображаемых файлов.
D По дате (сперва более старые)
Префикс "-" обращает порядок
Мой код упростится вообще до минимума
Код:

@Echo off
rem Пути указываем без кавычек и без \ на конце
rem -------------------------------------------

Set HowMuch=1
Set Where=F:\Delete\Install
Call :LimCountDir "%Where%" %HowMuch%

Set HowMuch=5
Set Where=\\SERVER_NT\{Общая}\Delete\Install
Call :LimCountDir "%Where%" %HowMuch%

GoTo :Eof

:LimCountDir
FOR /F "usebackq skip=%2 delims=" %%i IN (`Dir /B /A:D /O:-D "%~1\"`) DO Rd "%~1\%%i" /S /Q
GoTo :Eof


Bullet-Avalon 16-09-2010 10:11 1496521

Спасибо Вам большое, опробовал ваш скрипт megaloman, все отлично работает!
Благодарю всех.

kiripanda 16-09-2010 17:49 1496964

Цитата:

Цитата megaloman
Так Вы оставите самые старые папки.»

Упс. Не посмотрел на порядок сортировки, ибо не тестировал. Действительно, нужен
Цитата:

"Префикс "-" обращает порядок"
Цитата:

Цитата megaloman
Мой код упростится вообще до минимума »

Можно обойтись без Set
Код:

@Echo off
rem Пути указываем без \ на конце
rem -----------------------------

Call :LimCountDir "F:\Delete\Install" 1

Call :LimCountDir "\\SERVER_NT\{Общая}\Delete\Install" 5

GoTo :Eof

:LimCountDir
FOR /F "usebackq skip=%2 delims=" %%i IN (`Dir /B /A:D /O:-D "%~1\"`) DO Rd "%~1\%%i" /S /Q
GoTo :Eof


megaloman 16-09-2010 19:19 1497031

kiripanda,Очевидно
Цитата:

Можно обойтись без Set
Однако я придерживаюсь обычно такого стиля: в начале я определяю некие исходные параметры задачи, что требует ряд Set, а затем уже рисую сам батник. Надо было бы написать:
Код:

Echo off
rem Пути указываем без кавычек и без \ на конце
rem -------------------------------------------

Set HowMuch1=1
Set Where1=F:\Delete\Install

Set HowMuch2=5
Set Where2=\\SERVER_NT\{Общая}\Delete\Install

Call :LimCountDir "%Where1%" %HowMuch1%
Call :LimCountDir "%Where2%" %HowMuch2%

GoTo :Eof

:LimCountDir
FOR /F "usebackq skip=%2 delims=" %%i IN (`Dir /B /A:D /O:-D "%~1\"`) DO Rd "%~1\%%i" /S /Q
GoTo :Eof

Обычно я еще и комментарии пишу к исходным данным. Делаю это для того, чтобы максимально надёжно и быстро перенастроить батник, если условия поменялись. В принципе, для уменьшения числа строк кода, можно обойтись и без Call. В угоду краткости я не иду на ухудшение в удобстве использования. Однако, в примере я отошел от этого правила, так как смысл имела только процедура, а всё остальное - тестовые строки.


Время: 10:46.

Время: 10:46.
© OSzone.net 2001-