PDA

Показать полную графическую версию : Не работает BAT файл - прошу помощи


Hiris333
19-10-2019, 09:29
Общая цель: в папку D:\backup_\work\source ежедневно архивируются базы 1с
Нужно каждый день запускать скрипт, который будет оставлять в этой папке только файлы за с датой модификации не старше года, из оставшихся должны удаляться все коме тех, которые:
1) имеют дату модификации совпадающую с первым числом каждого месяца.
2) имеют день недели модификации соответветствующий одной из пятниц каждой недели за последние 30 дней.
4) все файлы за последнюю неделю.

Начала ваять такой скрипт и столкнулась с трудностями при передаче значений переменных в циклах for.

Вот что я предлагаю

rem @echo off
Setlocal EnableDelayedExpansion
rem Удаляем файлы старше года
FORFILES.exe /p "D:\backup_\work\source" /M *.* /C "cmd /c del /f /q @file" /d -365
rem Перемещение файлов старше недели в папку "a". В папке source остаются файлы за последнюю неделю
FORFILES.exe /p "D:\backup_\work\source" /M *.* /C "cmd /c move /y @file D:\backup_\work\a" /d -7
rem Перемещение файлов старше месяца из папки "a" в папку "b". В папке "a" остаются файлы старше недели, но с возрастом до 30 дней
FORFILES.exe /p "D:\backup_\work\a" /M *.* /C "cmd /c move /y @file D:\backup_\work\b" /d -30
rem Перемещаем файлы старше недели, но младше месяца созданные в любую пятницу из папки "а" в source, а остальные файлы кидаем в "с"

set dirA=d:\backup_\work\a
for %%D in (%dirA%\*) do (call :calcDayWeek "%%D")

goto :eof

:calcDayWeek
set "sourcePath=%1"
pause
echo %sourcePath%
rem Получение даты модификации файла:
for %%i in ("%sourcePath%") do (
for /f "tokens=1-5 delims=.: " %%j in ("%%~ti") do (
set mydate=%%j.%%k.%%l
)
)
echo %mydate%
rem вычисляем день недели модификации этого файла
set /a y=%mydate:~6,4%&
set /a m=1%mydate:~3,2%-100&
set /a d=1%mydate:~0,2%-100

set /a i=(%y%-1901)*365+(%y%-1901)/4+%d%+(!(%y% %% 4))*(!((%m%-3)^&16))
set /a i=(%i%+(%m%-1)*30+2*(!((%m%-7)^&16))-1+((65611044^>^>(2*%m%))^&3))%%7+1
echo %i%

if %i%==5 ((move "%sourcePath%" d:\backup_\work\source) & pause) else (move "%sourcePath%" d:\backup_\work\c )
exit /B

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

Iska
19-10-2019, 11:04
Hiris333, работа с датами — не самая сильная сторона пакетных файлов. Рекомендую пользовать WSH/PowerShell.

В переменную mydate значение даты не передается, »
Какие-то пробельные символы в именах файлов есть (пробелы, запятые и т.п.)? Попробуйте так:
for %%D in ("%dirA%\*.*") do (call :calcDayWeek "%%~D")

set "sourcePath=%~1"

Hiris333
19-10-2019, 19:23
Спасибо! Помогло. Да действительно, имена файлов с пробелами. После ввода тильды - все пошло. :-)

Я поняла тильда здесь нужна чтобы потом кавычки отменялись... С WSH/PowerShell пока дело не имела - надо копнуть как-нибудь. Я старой закалки. Еще с ПК на дискетах игралась...

megaloman
19-10-2019, 22:03
Hiris333, Вот вариант:@Echo Off
cls
rem Дата в системе должна быть в формате дд.мм.гггг

Set "Bak=Z:\backup_\work\source"
Call :JulianDay %Date:~0,2% %Date:~3,2% %Date:~6,4% "Now" "DoW"

Pushd "%Bak%" &&FOR /F "usebackq delims=" %%f IN (`2^>nul Dir "%Bak%" /B /A:-D /O:D`) DO (
Set "DF=%%~tf"
Call :JulianDay %%DF:~0,2%% %%DF:~3,2%% %%DF:~6,4%% "Dfile" "DoW"
Call Set /A Delta=%Now%-%%Dfile%%
Call :MyDel "%Bak%\%%f" %%Delta%% 7 %%DoW%% 5 30 %%DF:~0,2%% 01 365
rem 1 2 3 4 5 6 7 8 9
)
Popd
Exit /B 0

rem Вычисляет абсолютный номер дня по юлианскому календарю и номер дня в неделе
rem На входе dd mm yyyy
rem На выходе имя переменной в кавычках четвёртым и пятым аргументом

:JulianDay
SetLocal
Set "D=0%1" &Set "M=0%2"
Set /A D=1%D:~-2%-100 &Set /A M=1%M:~-2%-100
Set /A JD=(1461*(%3+4800+(%M%-14)/12))/4+(367*(%M%-2-12*((%M%-14)/12)))/12-(3*((%3+4900+(%M%-14)/12)/100))/4+%D%-32075
Set /A DW=((%3-1901)*365 + (%3-1901)/4 + %D% + (!(%3 %% 4))*(!((%M%-3)^&16))+(%M%-1)*30+2*(!((%M%-7)^&16))-1+((65611044^>^>(2*%M%))^&3))%%7+1
EndLocal &(Set /A %~4=%JD%, %~5=%DW%)
Exit /B 0

:MyDel
If %2 LSS %3 Exit /B 0
If %2 LSS %6 If %4 EQU %5 Exit /B 0
If %2 LSS %9 If %7 == %8 Exit /B 0
Del %1
Exit /B 0

YuS_2
20-10-2019, 14:33
Общая цель: в папку D:\backup_\work\source ежедневно архивируются базы 1с
Нужно каждый день запускать скрипт, который будет оставлять в этой папке только файлы за с датой модификации не старше года, из оставшихся должны удаляться все коме тех, которые:
1) имеют дату модификации совпадающую с первым числом каждого месяца.
2) имеют день недели модификации соответветствующий одной из пятниц каждой недели за последние 30 дней.
4) все файлы за последнюю неделю. »

Переформулирую постановку. Надо оставить файлы:
1. Все за последние 7 дней
2. Все пятничные файлы за последние 30 дней
3. Все файлы с первым числом месяца за последние 365 дней »

На powershell, это могло бы выглядеть так:
$folder = 'D:\backup_\work\source'
$a = get-date

dir $folder -rec -file|?{
($_.lastwritetime -ge $a.adddays(-30) -and `
$_.lastwritetime -lt $a.adddays(-7) -and `
$_.lastwritetime.dayofweek -ne 5 -and `
$_.lastwritetime.day -ne 1) -or `
($_.lastwritetime -ge $a.adddays(-365) -and `
$_.lastwritetime -lt $a.adddays(-30) -and `
$_.lastwritetime.day -ne 1) -or `
$_.lastwritetime -lt $a.adddays(-365)
}|del -rec -force

Hiris333
21-10-2019, 06:36
Абалдеть!!! Готовые решения...
Вы меня балуете :)))
Спасибо!!!
Изящно!
Про Powershell тоже спасибо!!!
Поучительно! Буду разбираться.




© OSzone.net 2001-2012