1

Тема: WSH,VBS,JS: Архивация и перемещение файлов в NAS

Добрый день.
Ситуация такая: 1С формирует логи каждый день и сохраняет их локальную папку например C:\log.
Чтобы не вычищать вручную, я создал batник на перемещение файлов с периодом 1 сутки перемещение файлов старше одного дня. Но можно ли создать скрипт, который будет архивировать файлы старше одного дня , удалять заархивированные файлы с диска и перемещать подготовленный архив на указанное место в локальной сети, например на \\nas\*\наименование папки.
Дальше bat я не делал скрипты и VBS для меня пока не сеянное поле, если есть подобный скрипт , то прошу помочь. Заранее благодарю

2

Re: WSH,VBS,JS: Архивация и перемещение файлов в NAS

Добрый день.
А каким архиватором будете пользоваться?
У некоторых архиваторов такие богатые возможности (командная строка), что не нужно и программу писать.
Например, с помощью WinRAR:


@echo off & title %~nx0 & SetLocal EnableExtensions EnableDelayedExpansion
  rem Папка логов:
  set "sDirLog=C:\LOG"
  rem  Папка архивов, можно заменить "C:\LOG\ARH" на "\\nas\*\наименование папки":
  set "sDirArh=C:\LOG\ARH"
  md "!sDirArh!" >nul 2>&1
  call "rar.exe" m -ag#yymmdd-hhmmss -ep1 -to1d "!sDirArh!\" "!sDirLog!\*.log"

    m[f]    Переместить в архив [только файлы].
    -ag[формат]
            Добавить к имени архива текущие дату и время.
            Этот ключ добавляет к имени архива текущие дату и время при
            создании или обработке архива. Может пригодиться при регулярном
            создании резервных копий.
    -ep1    Исключить базовый каталог из имён.
    -to<период>
            Обрабатывать файлы более старые, чем указанный период времени.
            Задающая время строка имеет следующий формат:
            [<дни>d][<часы>h][<минуты>m][<секунды>s]

3

Re: WSH,VBS,JS: Архивация и перемещение файлов в NAS

andypetr Я планировал бесплатный 7zip, с ним возможно провести такие манипуляции?

4 (изменено: andypetr, 2023-07-11 12:20:05)

Re: WSH,VBS,JS: Архивация и перемещение файлов в NAS

Classified, к сожалению у 7-zip я не нашёл такой замечательной возможности (отбор файлов по дате).

У меня для такой достаточно простой задачи (типа удаления старых логов) больше лежит душа к использованию BAT.
Просто сам код лаконичнее получается, чем было бы на VBS: не нужно возиться с объектами FileSystemObject, File, TextStream и т.п.
Если всё же есть необходимость реализовать это именно в VBS/JS и не устраивает "костыль" описанный ниже - то можно и на VBS это изобразить.
Но будет не 15 строк, а в 2-3 раза больше.

Основная проблема с BAT - это сравнение дат.
В примере ниже используются процедуры от dostips.com для определения у даты файла юлианского номера дня.
Соответственно, мы сегодня архивируем файлы не точно с суточной разницей в датах, а просто вчерашние и более поздние - время не участвует в сравнении, только сама дата.

@echo off & title %~nx0 & SetLocal EnableExtensions EnableDelayedExpansion

  rem Папка логов:
  set "sDirLog=C:\LOG"

  rem Папка архивов, можно заменить "C:\LOG\ARH" на "\\nas\*\наименование папки":
  set "sDirArh=C:\LOG\ARH"
  md "!sDirArh!" >nul 2>&1

  rem Маска LOG-файлов:
  set "sMaskLog=*.log"

  rem Временный файл, будет содержать список архивируемых .log-файлов.
  set "sFileTmp=%TEMP%\%~n0_%RANDOM%.tmp"

  rem nNow = сегодняшняя дата.
  call :jDate nNow

  rem Файл-архива, в имени содержится текущая дата:
  call :jdate2date !nNow! nYYYY nMM nDD
  set "sFileArh=!sDirArh!\#!nYYYY!!nMM!!nDD!.7z"

  rem Заполнение списка по условию: дата создания файла меньше сегодняшней (nFile < nNow).
  for %%a in ("!sDirLog!\!sMaskLog!") do (
    call :fTime nFile "%%~a"
    if !nFile! lss !nNow! echo.%%~a>>"!sFileTmp!"
  )

  if exist "!sFileTmp!" (
    rem -scsDOS задаёт кодировку DOS для списка файлов sFileTmp (чтобы не было проблем с кириллицей, по ум. у 7z: UTF-8)
    rem -sdel удаляет архивированные файлы 
    call "7z.exe" a "!sFileArh!" "@!sFileTmp!" -scsDOS -sdel
    del /q "!sFileTmp!" >nul 2>&1
    echo.
    if exist "!sFileArh!" echo.Создан архив: "!sFileArh!"
  ) else (
    echo.*** Нет подходящих файлов для архивирования!
  )
  pause

Endlocal
exit /b

rem ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:ftime JD filename attr -- returns the file time in julian days
::                      -- JD    [out]    - valref file time in julian days
::                      -- attr  [in,opt] - time field to be used, creation/last-access/last-write, see 'dir /?', i.e. /tc, /ta, /tw, default is /tw
:$created 20060101 :$changed 20090322 :$categories DateAndTime
:$source http://www.dostips.com
SETLOCAL
  set file=%~2
  set attr=%~3
  if not defined attr (call:jdate JD "- %~t2"
  ) ELSE (for /f %%a in ('"dir %attr% /-c "%file%"|findstr "^^[0-9]""') do call:jdate JD "%%a")
ENDLOCAL & IF "%~1" NEQ "" (SET %~1=%JD%) ELSE (echo.%JD%)
EXIT /b

:jdate JD DateStr -- converts a date string to julian day number with respect to regional date format
::                -- JD      [out,opt] - julian days
::                -- DateStr [in,opt]  - date string, e.g. "03/31/2006" or "Fri 03/31/2006" or "31.3.2006"
:$reference http://groups.google.com/group/alt.msdos.batch.nt/browse_frm/thread/a0c34d593e782e94/50ed3430b6446af8#50ed3430b6446af8
:$created 20060101 :$changed 20080219
:$source http://www.dostips.com
SETLOCAL

  set DateStr=%~2&if "%~2"=="" set DateStr=%date%

  for /f "skip=1 tokens=2-4 delims=(-)" %%a in ('"echo.|date"') do (
      for /f "tokens=1-3 delims=/.- " %%A in ("%DateStr:* =%") do (
          set %%a=%%A&set %%b=%%B&set %%c=%%C))

  rem { дд-мм-гг или dd-mm-yy в выводе "echo.|date"
  if /i "%гг%" == "" (
    set /a "yy=10000%yy% %%10000,mm=100%mm% %% 100,dd=100%dd% %% 100"
  ) else (
    set /a "yy=10000%гг% %%10000,mm=100%мм% %% 100,dd=100%дд% %% 100"
  )
  rem }

  set /a JD=dd-32075+1461*(yy+4800+(mm-14)/12)/4+367*(mm-2-(mm-14)/12*12)/12-3*((yy+4900+(mm-14)/12)/100)/4

ENDLOCAL & IF "%~1" NEQ "" (SET %~1=%JD%) ELSE (echo.%JD%)
EXIT /b

:jdate2date JD YYYY MM DD -- converts julian days to gregorian date format
::                     -- JD   [in]  - julian days
::                     -- YYYY [out] - gregorian year, i.e. 2006
::                     -- MM   [out] - gregorian month, i.e. 12 for december
::                     -- DD   [out] - gregorian day, i.e. 31
:$reference http://aa.usno.navy.mil/faq/docs/JD_Formula.html
:$created 20060101 :$changed 20080219 :$categories DateAndTime
:$source http://www.dostips.com
SETLOCAL ENABLEDELAYEDEXPANSION
set /a L= %~1+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
set MM=%MM:~-2%
set DD=%DD:~-2%
( ENDLOCAL & REM RETURN VALUES
    IF "%~2" NEQ "" (SET %~2=%YYYY%) ELSE echo.%YYYY%
    IF "%~3" NEQ "" (SET %~3=%MM%) ELSE echo.%MM%
    IF "%~4" NEQ "" (SET %~4=%DD%) ELSE echo.%DD%
)
EXIT /b

5

Re: WSH,VBS,JS: Архивация и перемещение файлов в NAS

andypetr Спасибо, пробовал. Сменил директории в коде, но в итоге абра-кадабра получилась. Не понимаю, где ошибка.

Post's attachments

пример.jpg 16.59 kb, file has never been downloaded. 

You don't have the permssions to download the attachments of this post.

6

Re: WSH,VBS,JS: Архивация и перемещение файлов в NAS

Classified, это сообщение из текста программы: "*** Нет подходящих файлов для архивирования!", выведенное в консоль (кодировка символов DOS-866) из созданного вами BAT-файла в кодировке UTF-8. Нужно было создавать файл с кодировкой DOS-866 и вставлять туда текст программы.
Я прикрепляю свой BAT-файл (в архиве), он уже в нужной кодировке.
Для последующего редактирования можно использовать любой программный редактор (Notepad++ и др.), задавая кодировку исходного текста DOS-866.
Лично я пользуюсь встроенным редактором FAR.

Добавил в код строку с уменьшением номера текущего дня.

  • если отнимать 0 (или удалить строку) - то будет работать как раньше, удаляя вчерашние файлы и более ранние;

  • если отнимать 1 - удаляются позавчерашние файлы и более ранние (вчерашние не трогаем, т.к. могли быть созданы менее 24 часов назад);

  • и т.д.

  rem Можно уменьшить nNow, чтобы архивировать файлы старше вчерашних.
  set /a nNow = nNow - 1
Post's attachments

log2nas.zip 2.13 kb, file has never been downloaded. 

You don't have the permssions to download the attachments of this post.

7

Re: WSH,VBS,JS: Архивация и перемещение файлов в NAS

Ну и как-то неспокойно мне на душе, что в разделе VBS/JS мы BAT-файлами увлеклись.
Для очистки совести привожу аналогичное решение на VBS.

' Можно требовать объявления переменных, раскомментировав строчку:
' Option Explicit

' В случае ошибки переходить к следующему оператору
On Error Resume Next
' Альтернатива - в случае ошибки прекращать выполнение программы:
' On Error GoTo 0

	' Полезные объекты для работы:
	Set goShellApp = CreateObject("Shell.Application")
	Set goWsShell  = CreateObject("WScript.Shell")
	Set goFSO      = CreateObject("Scripting.FileSystemObject")

	' Папка логов:
	sDirLog = "C:\LOG"

	' Папка архивов, можно заменить "C:\LOG\ARH" на "\\nas\*\наименование папки":
	sDirArh = "C:\LOG\ARH"
	goFSO.CreateFolder(gsDirArh)

	' Маска LOG-файлов:
	sMaskLog = "*.log"

	' Временный файл, будет содержать список архивируемых .log-файлов.
	sFileTmp = goFSO.BuildPath(goWsShell.ExpandEnvironmentStrings("%TEMP%"), goFSO.GetTempName())

	' dNow = сегодняшняя дата.
	dNow = Now()

	' Файл-архива, в имени содержится текущая дата:
	sFileArh = goFSO.BuildPath(sDirArh, "#" & myFormatDateYMD(dNow, "-") & ".7z")

	' Можно уменьшить nNow, чтобы архивировать файлы старше вчерашних.
	' 	* если отнимать 1 - удаляются вчерашние файлы и более ранние;
	' 	* если отнимать 2 - удаляются позавчерашние файлы и более ранние;
	' 	* и т.д.
	' Целые числа означают дни, дробные - части дня (часы, минуты, секунды).
	' Примеры: dNow = 12.07.2023 10:09:26, dNow - 1 = 11.07.2023 10:09:26 (минус день), dNow - 1/24 = 12.07.2023 09:09:26 (минус час), dNow - 1/24/60 = 12.07.2023 10:08:26 (минус минута).
	dNow = dNow - 1

	' Заполнение списка по условию: дата создания файла меньше сегодняшней (dFile < dNow).
	sFiles = ""

	Set oFiles = goFSO.GetFolder(sDirLog).Files
	For Each oFile In oFiles
		If StrComp(goFSO.GetExtensionName(oFile.Path), goFSO.GetExtensionName(sMaskLog), vbTextCompare) = 0 Then
			' Проверяется дата изменения, можно проверять и на дату создания: oFile.DateCreated.
			If oFile.DateLastModified < dNow Then
				sFiles = sFiles & oFile.Path & vbCrLf
			End If
		End If
	Next 'oFile
	Set oFiles = Nothing
	Set oFile  = Nothing

	If sFiles = "" Then
		WScript.Echo "*** Нет подходящих файлов для архивирования!"
	Else

		' Записываем список файлов в sFileTmp
		With goFSO.CreateTextFile(sFileTmp, True) 'File, Overwrite
			.Write(sFiles)
			.Close
		End With

		' Архивируем:
	    ' -scsWIN задаёт кодировку WIN для списка файлов sFileTmp (чтобы не было проблем с кириллицей, по ум. у 7z: UTF-8)
    	' -sdel удаляет архивированные файлы 

    	' Run(<Command>,<WindowStyle>,<WaitOnReturn>), WindowStyle - 0 Hidden - 1 Normal - 2 Minimized - 3 Maximized
    	goWsShell.Run Chr(34) & "7z.exe" & Chr(34) & " a " & Chr(34) & sFileArh & Chr(34) & " " & Chr(34) & "@" & sFileTmp & Chr(34) & " -scsWIN -sdel", 1, 1

		goFSO.DeleteFile sFileTmp, True 'File, Force_delete_read-only

		If goFSO.FileExists(sFileArh) Then
			WScript.Echo "Создан архив: " & sFileArh
		Else
			WScript.Echo "*** Ошибка создания архива: " & sFileArh
		End If

	End If
	  
	' По окончании работы программы желательно/необходимо все созданные объекты удалить:
	Set goShellApp = Nothing
	Set goWsShell  = Nothing
	Set goFSO      = Nothing

' Выход с кодом возврата
WScript.Quit(0)

''''''''''''''''''''''''''''''''''
'"29.10.2019", "-" => "2019-10-29"
''''''''''''''''''''''''''''''''''
Function myFormatDateYMD(dDate, sSep)
  myFormatDateYMD = Right("0000" & DatePart("yyyy", dDate), 4) & sSep & _
                    Right("00"   & DatePart("m"   , dDate), 2) & sSep & _
                    Right("00"   & DatePart("d"   , dDate), 2) 
End Function