Скрипты для CMD

Скрипты выполняемые интерпретатором CMD.EXE - стандартной консольной оболочкой для Win2000/WinXP/Vista/Seven/Win8/Win2000 Server/Win2003/Win2008.
Иначе говоря - пакетники. Иногда еще их(не вполне оправданно) называют батниками, но классический батник использует возможности обеспечиваемые оболочкой предыдущих систем COMMAND.COM, возможности которого существенно меньше.

Теги: 

Выключение компьютеров в домене по списку

Монолитный скрипт выключения компьютеров в домене по списку:
@ECHO OFF
SET "BEGIN_MARKER=:ENDFILE1"
SET "END_MARKER=:ENDFILE2"
FOR /F "usebackq tokens=1 delims=:" %%a IN (`FINDSTR /N /B /C:"%BEGIN_MARKER%" "%~0"`) DO SET "SKIP_LINE=%%a"
CALL :WORK "%SKIP_LINE%" "%END_MARKER%" "%~0"
GOTO :EOF

:WORK
FOR /F "usebackq skip=%~1 tokens=1 eol=; delims=" %%a IN (`TYPE "%~3"`) DO IF NOT "%%a"=="%~2" (CALL :PROCEDURE "%%a") ELSE (GOTO :EOF)
GOTO :EOF

:PROCEDURE
(ping -n 1 %~1|FIND /I "TTL=")&&(
ECHO Комп "\\%~1" Включен - выключаю...
shutdown -f /s /m \\%~1 -t 1
)||ECHO Комп "\\%~1" выключен
GOTO :EOF

:ENDFILE1
PC1
PC2
PC3
:ENDFILE2

Единый логон-скрипт для AD

Моя попытка навести порядок и унификацию при подключении сетевых дисков в AD.

Возможна работа как через индивидуальные групповые политики, так и через политику AD по-умолчанию.

Идея состоит в следующем: храним описание вариантов подключений в текстовых файлах, с указанием группы для которой это работает, и анализируем при запуске грeппы конкретного пользователя с использованием dsget и dsquery.

Структура хранимых описаний такова: групповые и общедоменные назначачения хранятся в едином файле расположенном в корне NETLOGON(возможны варианты), а пользовательские назначения располагаются в папках с пользовательским именем входа  в систему.
Также в отдельных файлах храним описание запускаемых скриптов для групп и пользователей.

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

Структура решения:
\dsget.exe - файл из RK для получения списка групп пользователя
\dsquery.dll- файл из RK для получения списка групп пользователя
\dsquery.exe- файл из RK для получения списка групп пользователя
\logon.cmd - собственно тело скрипта
\logon.vbs - костыль для запуска без отображения окна консоли - именно он должен быть назначен в качестве логон скрипта
\rs_list.txt - список групповых и общедоменных назначений подключаемых дисков с указанием группы
\sc_list.txt - список групповых и общедоменных назначений выполняемых скриптов с указанием группы
\_SCRIPT\ - папка с групповыми и общедоменными скриптами
\_SCRIPT\1C.cmd - пример скрипта
\USER1\rs_list.txt- список назначений подключаемых дисков для конкретного пользователя(без указания группы)
\USER1\sc_list.txt- список назначений выполняемых скриптов для конкретного пользователя(без указания группы)
\USER2\rs_list.txtсписок назначений подключаемых дисков для конкретного пользователя(без указания группы)
\USER2\sc_list.txt- список назначений выполняемых скриптов для конкретного пользователя(без указания группы)
Прикрепляю файл с телом скрипта и тестовой структурой.

Приветствуются пожелания по доработке ;)
Добавил ключ рекурсивного анализа вхождения в группы.

И на всякий случай тело скрипта в текстовом виде:



@ECHO OFF
:: Буквы дисков зарезервированные под пользовательские сетевые подключения
SET "EXLUDE_LETTER=D: E: F: J: H: I: J:"
"%~dp0dsquery.exe" user -d "%USERDOMAIN%" -samid "%USERNAME%"|^
%~dp0dsget.exe user -memberof |findstr /I /C:"CN=Domain Users,"&&(
:: Удаление текущих сетевых подключений
FOR /F "usebackq tokens=2 delims= " %%a IN (`net use^|find ":"^|find "\\"^|FINDSTR /V /I "%EXLUDE_LETTER%"`) DO (
1>NUL 2>&1 NET USE /DELETE %%a)
:: Добавление групповых сетевых подключений
IF EXIST "%~dp0rs_list.txt" (
FOR /F "usebackq tokens=1,2,3 eol=; delims=|" %%a IN (`TYPE "%~dp0rs_list.txt"^|FIND "\\"`) DO (
"%~dp0dsquery.exe" user -d "%USERDOMAIN%" -samid "%USERNAME%"|^
%~dp0dsget.exe user -memberof -expand |1>NUL 2>&1 findstr /I /C:"CN=%%~c,"&&(
1>NUL 2>&1 NET USE %%a: %%b /PERSISTENT:NO)))
:: Выполнение групповых скриптов
IF EXIST "%~dp0sc_list.txt" (
FOR /F "usebackq tokens=1,2 eol=; delims=|" %%a IN (`TYPE "%~dp0sc_list.txt"^|FINDSTR /I ".cmd .bat"`) DO (
"%~dp0dsquery.exe" user -d "%USERDOMAIN%" -samid "%USERNAME%"|^
%~dp0dsget.exe user -memberof -expand |1>NUL 2>&1 findstr /I /C:"CN=%%~b,"&&(
IF EXIST "%~dp0%%~a" CALL "%~dp0%%~a")))
:: Добавление пользовательских сетевых подключений
IF EXIST "%~dp0%USERNAME%\rs_list.txt" (
FOR /F "usebackq tokens=1,2 eol=; delims=|" %%a IN (`TYPE "%~dp0%USERNAME%\rs_list.txt"^|FIND "\\"`) DO (
1>NUL 2>&1 NET USE %%a: %%b /PERSISTENT:NO))
:: Выполнение пользовательских скриптов
IF EXIST "%~dp0%USERNAME%\sc_list.txt" (
FOR /F "usebackq tokens=1 eol=; delims=|" %%a IN (`TYPE "%~dp0%USERNAME%\sc_list.txt"^|FIND /I ".cmd"`) DO (
IF EXIST "%~dp0%%~a" CALL "%~dp0%%~a"))
)
EXIT 0
Файлы: 

Интерпретатор CMD - вывод переменных со спецсимволами на экран и в файл

Известная, но слабоосвещенная тема - обработка в коммандном интерпретаторе CMD данных со спецсимволами.
В большинстве ситуаций она вполне решаема...
Плюс к этому периодически возникают задачи вывода в файл без перевода строки.
Несколько лет назад (на ру-борде) я выкладывал семпловый код, который достаточно подробно иллюстрирует примеры возможной работы:

@ECHO OFF&CLS
(ECHO Обработка переменных со спецсимволами "(", ")","&","|",">","<")
(ECHO SET "AAA=сообщение()&|<>команда")
SET "AAA=сообщение()&|<>команда"

(ECHO Вывод на экран с обрамляющими двойными кавычками)
(ECHO ^(ECHO "%%AAA%%"^))
(ECHO "%AAA%")

(ECHO Перенаправление значения переменной в файл file.txt с переводом строки то есть с CR/LF)
(ECHO с заменой существующего file.txt)
(ECHO SET /p"=%%AAA%%"^<nul 1^>file.txt^&ECHO.^>^>file.txt)
SET /p"=%AAA%"<nul 1>file.txt&ECHO.>>file.txt

(ECHO Перенаправление значения переменной в файл file.txt с переводом строки то есть с CR/LF)
(ECHO дописыванием в существующий file.txt)
(ECHO SET /p"=%%AAA%%"^<nul 1^>^>file.txt^&ECHO. 1^>^>file.txt)
SET /p"=%AAA%"<nul 1>>file.txt&ECHO. 1>>file.txt

(ECHO Перенаправление значения переменной в файл file1.txt без перевода строки то есть без CR/LF)
(ECHO с заменой существующего file1.txt)
(ECHO SET /p"=%%AAA%%"^<nul 1^>file1.txt)
SET /p"=%AAA%"<nul 1>file1.txt

(ECHO Перенаправление значения переменной в файл file1.txt без перевода строки то есть без CR/LF)
(ECHO с дописыванием в существующий file1.txt)
(ECHO SET /p"=%%AAA%%"^<nul 1^>^>file1.txt)
SET /p"=%AAA%"<nul 1>>file1.txt

(ECHO Вывод значения переменной на экран с переводом строки то есть с CR/LF)
(ECHO SET /p"=%%AAA%%"^<nul^&ECHO.)
(ECHO ^(ECHO Вторая строка^))
SET /p"=%AAA%"<nul&ECHO.
(ECHO Вторая строка)

(ECHO Вывод значения переменной на экран без перевода строки то есть с CR/LF)
(ECHO SET /p"=%%AAA%%"^<nul)
(ECHO ^(ECHO Вторая строка^))
SET /p"=%AAA%"<nul
(ECHO Вторая строка)

(ECHO Метод предварительной подготовки: )
(ECHO SET "AAA=%%AAA:&=^&%%")
(ECHO SET "AAA=%%AAA:|=^|%%")
(ECHO SET "AAA=%%AAA:<=^<%%")
(ECHO SET "AAA=%%AAA:>=^>%%")
(ECHO SET "AAA=%%AAA:(=^(%%")
(ECHO SET "AAA=%%AAA:)=^)%%")
SET "AAA=%AAA:&=^&%"
SET "AAA=%AAA:|=^|%"
SET "AAA=%AAA:<=^<%"
SET "AAA=%AAA:>=^>%"
SET "AAA=%AAA:(=^(%"
SET "AAA=%AAA:)=^)%"
(ECHO ^(ECHO %%AAA%%^))
(ECHO %AAA%)
PAUSE

Кодировка приведенного скрипта CP866.
Для ознакомления рекомендуется выполнить ;)
Само-собой в случае вопросов постараюсь ответить...

Логофф сессий отключенных пользователей на терминальном сервере

Убить все отключенные сессии:

@ECHO OFF
FOR /F "USEBACKQ TOKENS=2 DELIMS= " %%a IN (`quser^|findstr /b /v "^>"^|findstr /i /v " ID "^|findstr /v /i "rdp-tcp"`) DO logoff %%~a
EXIT 0

Перевод столбца в строку

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

@ECHO OFF
:: Принимает четыре параметра из командной строки:
:: 1 - имя файла для обработки (обязательный!)
:: 2 - имя файла результата (необязательный!)
:: при незаданном параметре будет использован файл result.txt в текущей папке
SET FILE_RESULT=%~dp0result.txt
:: 3 - последовательность символов как разделитель для вывода (необязательный!)
:: при незаданном параметре будет использован символ
:: При указании ОБЯЗАТЕЛЬНО параметр брать в двойные кавычки!!!
SET RAZDEL=,
:: 4 - символ который будет использоваться для обрамления вывода по текущей строке (необязательный!)
:: при незаданном параметре будет использован символ '
:: При указании ОБЯЗАТЕЛЬНО параметр брать в двойные кавычки!!!
SET FRAME='
IF %~1==(
ECHO Имя файла для обработки не указано!
GOTO :ERR
)

IF NOT EXIST %~1 (
ECHO Файл для обработки не существует!
GOTO :ERR
)
IF NOT %~2== (
SET FILE_RESULT=%~2
)
IF NOT %~3== (
SET RAZDEL=%~3
)
IF NOT %~4== (
SET FRAME=%~4
)
FOR /F usebackq tokens=* delims= %%a IN (%~1) DO CALL :MAIN %%~a
GOTO :EOF
:MAIN
SET /p=%RAZDEL1%%FRAME%%~1%FRAME%<nul>>%FILE_RESULT%
SET RAZDEL1=%RAZDEL%
GOTO :EOF
:ERR
PAUSE
GOTO :EOF

Подключение к WSUS машины не входящей в домен

Идем в ветку реестра

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate]

Экспортируем ее в файл и добавляем в реестр ПК в домен не входящих. Это приведет к обращению на сервер указанный в ветке. Для проверки запускаем в командной строке: wuauclt /detectnow Смотрим логи C:\windows\WindowsUpdate.log, идем в конец файла и находим строку вида:

2013-03-23 18:13:56:375  908 1074 PT +++++++++++  PT: Synchronizing server updates  +++++++++++
2013-03-23 18:13:56:375  908 1074 PT   + ServiceId = {3DA21691-E39D-4DA6-8A4B-B43877BCB1B7}, Server URL = http://192.168.0.10:8080/ClientWebService/client.asmx

где 192.168.0.10 - имя сервера, на котором у нас крутится WSUS. Если нет, проверяем значения ключей реестра

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\WUServer HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\WUStatusServer

их значение должно соответствовать 192.168.0.10:8080. Если соответствует, перезагружаемся и проверяем еще раз, если не соответствует - правим значения, перезагружаемся, проверяем. Ветка реестра, отвечающий за настройку политики WindowsUpdate в общем виде выглядит приблизительно так:

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate]
"AcceptTrustedPublisherCerts"=dword:00000001
"WUServer"="http://192.168.0.10:8080"
"WUStatusServer"="http://192.168.0.10:8080"

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU]
"NoAutoUpdate"=dword:00000000
"AUOptions"=dword:00000003
"ScheduledInstallDay"=dword:00000000
"ScheduledInstallTime"=dword:00000010
"NoAutoRebootWithLoggedOnUsers"=dword:00000001
"DetectionFrequencyEnabled"=dword:00000001
"DetectionFrequency"=dword:00000008
"UseWUServer"=dword:00000001

Преобразование файлов 1CClientBankExchange в табличную форму

Лично мне периодически приходилось сталкиваться с обработкой данных не в табличной форме, а в "именованном формате" то есть когда каждый параметр пишется на отдельной строке в виде Параметр=Значение параметра причем файл имеет строго выраженную периодическую структуру и любой из параметров является необязательным. Порядок следования - произвольный.
Пример такого формата - стандартный формат 1С для общения с клиент-банками 1CClientBankExchange
На самом деле его можно даже средствами "малой механизации"(то есть чистый CMD-скрипт) преобразовать в табличную форму для дальнейшей обработки.
Привожу пример скрипта(кодировка Win1251):

@ECHO OFF CLS
COLOR 1E
CHCP 1251>NUL 2>&1

:: Папка с файлами для обработки. Полный путь в WIN1251!!!
SET "INPUT_DIR=D:\DATABASE"
:: Папка с выходными файлами. Полный путь в WIN1251!!!
:: Может совпадать с исходной папкой.
SET "OUTPUT_DIR=D:\DATABASE"
:: Папка для бэкапа входящих файлов. Полный путь в WIN1251!!!
:: Если она не указана то исходные файлы удалятся!!!
SET "BACKUP_DIR=D:\DATABASE\BACKUP"
:: Маска файлов для обработки
SET "FILE_MASK=to1c????.txt"

IF NOT EXIST "%INPUT_DIR%\" (ECHO Папка с файлами для обработки не найдена!&GOTO ERROR)
2>NUL DIR /B "%INPUT_DIR%\%FILE_MASK%"|1>NUL FIND /C /V ""||(ECHO Файлы для обработки не найдены!&GOTO ERROR)
IF NOT EXIST "%OUTPUT_DIR%" MD "%OUTPUT_DIR%"
IF NOT EXIST "%OUTPUT_DIR%" ECHO Не удалось создать папку для выходных файлов!&GOTO ERROR
IF NOT "%BACKUP_DIR%"=="" (
IF NOT EXIST "%BACKUP_DIR%" MD "%BACKUP_DIR%"
IF NOT EXIST "%BACKUP_DIR%" ECHO Не удалось создать папку для бэкапа файлов!&GOTO ERROR
)

ECHO Представляем системную дату в удобном виде:
ECHO wscript.ECHO YEAR(DATE) ^& RIGHT(0 ^& MONTH(DATE),2) ^& RIGHT(0 ^& DAY(DATE),2)>"%TEMP%\tmp.vbs"
FOR /F %%i IN ('cscript "%TEMP%\tmp.vbs" //Nologo') DO SET "TEKDATA=%%i"
IF EXIST "%TEMP%\tmp.vbs" DEL "%TEMP%\tmp.vbs"
ECHO %TEKDATA%

SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "usebackq" %%i IN (`DIR /B /A:-D "%INPUT_DIR%\%FILE_MASK%"`) DO (0<"%INPUT_DIR%\%%i" SET /P "LINE_1=") &IF /I "!LINE_1!"=="1CClientBankExchange" CALL :MAIN "%%i"
ENDLOCAL
EXIT

:MAIN
SET "FILE_NAME=%~1"
SET "NEWFILE_NAME=%TEKDATA%_%~1"
ECHO Выводим строку заголовков
1>"%OUTPUT_DIR%\%NEWFILE_NAME%" (ECHO 01-Номер^|02-Дата^|03-Сумма^|04-ДатаСписано^|05-Плательщик^|06-ПлательщикИНН^|07-ПлательщикКПП^|08-Плательщик1^|09-ПлательщикСчет^|10-ПлательщикРасчСчет^|11-ПлательщикБанк1^|12-ПлательщикБанк2^|13-ПлательщикБИК^|14-ПлательщикКорсчет^|15-ДатаПоступило^|16-Получатель^|17-ПолучательИНН^|18-ПолучательКПП^|19-Получатель1^|20-ПолучательСчет^|21-ПолучательРасчСчет^|22-ПолучательБанк1^|23-ПолучательБанк2^|24-ПолучательБИК^|25-ПолучательКорсчет^|26-ВидПлатежа^|27-ВидОплаты^|28-СтатусСоставителя^|29-ПоказательКБК^|30-ОКАТО^|31-ПоказательОснования^|32-ПоказательПериода^|33-ПоказательНомера^|34-ПоказательДаты^|35-ПоказательТипа^|36-СрокПлатежа^|37-Очередность^|38-НазначениеПлатежа^|39-Имя файла для приема^|)

SET "POINTER="
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "USEBACKQ TOKENS=1* DELIMS== " %%a in ("%INPUT_DIR%\%FILE_NAME%") DO (
IF "%%a"=="КонецДокумента" CALL :TOFILE&SET "POINTER=0"
IF !POINTER!==1 (IF NOT "%%~b"=="" (
IF /I "%%~a"=="Номер" SET "PP_1=%%~b"
IF /I "%%~a"=="Дата" SET "PP_2=%%~b"
IF /I "%%~a"=="Сумма" SET "PP_3=%%~b"
IF /I "%%~a"=="ДатаСписано" SET "PP_4=%%~b"
IF /I "%%~a"=="Плательщик" SET "PP_5=%%~b"
IF /I "%%~a"=="ПлательщикИНН" SET "PP_6=%%~b"
IF /I "%%~a"=="ПлательщикКПП" SET "PP_7=%%~b"
IF /I "%%~a"=="Плательщик1" SET "PP_8=%%~b"
IF /I "%%~a"=="ПлательщикСчет" SET "PP_9=%%~b"
IF /I "%%~a"=="ПлательщикРасчСчет" SET "PP_10=%%~b"
IF /I "%%~a"=="ПлательщикБанк1" SET "PP_11=%%~b"
IF /I "%%~a"=="ПлательщикБанк2" SET "PP_12=%%~b"
IF /I "%%~a"=="ПлательщикБИК" SET "PP_13=%%~b"
IF /I "%%~a"=="ПлательщикКорсчет" SET "PP_14=%%~b"
IF /I "%%~a"=="ДатаПоступило" SET "PP_15=%%~b"
IF /I "%%~a"=="Получатель" SET "PP_16=%%~b"
IF /I "%%~a"=="ПолучательИНН" SET "PP_17=%%~b"
IF /I "%%~a"=="ПолучательКПП" SET "PP_18=%%~b"
IF /I "%%~a"=="Получатель1" SET "PP_19=%%~b"
IF /I "%%~a"=="ПолучательСчет" SET "PP_20=%%~b"
IF /I "%%~a"=="ПолучательРасчСчет" SET "PP_21=%%~b"
IF /I "%%~a"=="ПолучательБанк1" SET "PP_22=%%~b"
IF /I "%%~a"=="ПолучательБанк2" SET "PP_23=%%~b"
IF /I "%%~a"=="ПолучательБИК" SET "PP_24=%%~b"
IF /I "%%~a"=="ПолучательКорсчет" SET "PP_25=%%~b"
IF /I "%%~a"=="ВидПлатежа" SET "PP_26=%%~b"
IF /I "%%~a"=="ВидОплаты" SET "PP_27=%%~b"
IF /I "%%~a"=="СтатусСоставителя" SET "PP_28=%%~b"
IF /I "%%~a"=="ПоказательКБК" SET "PP_29=%%~b"
IF /I "%%~a"=="ОКАТО" SET "PP_30=%%~b"
IF /I "%%~a"=="ПоказательОснования" SET "PP_31=%%~b"
IF /I "%%~a"=="ПоказательПериода" SET "PP_32=%%~b"
IF /I "%%~a"=="ПоказательНомера" SET "PP_33=%%~b"
IF /I "%%~a"=="ПоказательДаты" SET "PP_34=%%~b"
IF /I "%%~a"=="ПоказательТипа" SET "PP_35=%%~b"
IF /I "%%~a"=="СрокПлатежа" SET "PP_36=%%~b"
IF /I "%%~a"=="Очередность" SET "PP_37=%%~b"
IF /I "%%~a"=="НазначениеПлатежа" SET "PP_38=%%~b"
SET "PP_39=\\%COMPUTERNAME%@%INPUT_DIR%\%FILE_NAME%"
)
)
IF /I "%%a"=="СекцияДокумент" (SET "POINTER=1"&CALL :INIT)
)
ENDLOCAL
ECHO Формирование файла "%OUTPUT_DIR%\%NEWFILE_NAME%" формата текст с разделителями завершено!
IF NOT EXIST "%BACKUP_DIR%\%TEKDATA%" MD "%BACKUP_DIR%\%TEKDATA%"
IF NOT "%BACKUP_DIR%"=="" (MOVE /Y "%INPUT_DIR%\%FILE_NAME%" "%BACKUP_DIR%\%TEKDATA%") ELSE (DEL /Q /F "%INPUT_DIR%\%FILE_NAME%")
GOTO :EOF

:INIT
FOR /L %%z IN (1,1,39) DO SET "PP_%%z="
GOTO :EOF

:TOFILE
ECHO Вывод платежки N %PP_1% в файл "%OUTPUT_DIR%\%NEWFILE_NAME%"
FOR /L %%z IN (1,1,39) DO (
1>>"%OUTPUT_DIR%\%NEWFILE_NAME%" SET /P "=!PP_%%z!^|" >"%OUTPUT_DIR%\%NEWFILE_NAME%" (ECHO.)
GOTO :EOF

:ERROR
PAUSE
COLOR

При этом получим на выходе текстовый файл с разделителем "|" между полями.
Первой строкой будет выведена строка заголовков:
01-Номер|
02-Дата|
03-Сумма|
04-ДатаСписано|
05-Плательщик|
06-ПлательщикИНН|
07-ПлательщикКПП|
08-Плательщик1|
09-ПлательщикСчет|
10-ПлательщикРасчСчет|
11-ПлательщикБанк1|
12-ПлательщикБанк2|
13-ПлательщикБИК|
14-ПлательщикКорсчет|
15-ДатаПоступило|
16-Получатель|
17-ПолучательИНН|
18-ПолучательКПП|
19-Получатель1|
20-ПолучательСчет|
21-ПолучательРасчСчет|
22-ПолучательБанк1|
23-ПолучательБанк2|
24-ПолучательБИК|
25-ПолучательКорсчет|
26-ВидПлатежа|
27-ВидОплаты|
28-СтатусСоставителя|
29-ПоказательКБК|
30-ОКАТО|
31-ПоказательОснования|
32-ПоказательПериода|
33-ПоказательНомера|
34-ПоказательДаты|
35-ПоказательТипа|
36-СрокПлатежа|
37-Очередность|
38-НазначениеПлатежа|
39-Имя файла для приема|

Само-собой не в приведенном виде - а в виде одной строки ;)

Страховое копирование по списку

Относительно простой вариант резервного копирования по списку файлов/папок с учетом типа резервной копии и количества хранимых копий по типам. Классические типы: дневная-недельная-месячная-годовая копии. Кодировка скрипта CP866. В приаттаченом файле содержится сам скрипт, пример файла списка и консольные версии архиватора 7z.

@ECHO OFF CLS SETLOCAL :: Папка для хранения резервных копий - если надо не текущую впишите свою
:: По-умолчанию текущая папка
SET "BACKUP_DIR=%~dp0"
:: Постоянная часть имени архива - для уникальной идентефикации архива
SET "SOURCE_NAME=MY_BACKUP_1"
:: Имя и месторасположение файла со списком для резервного копирования
:: Имена папок пишутся либо с символом "\" в конце либо без него
SET "BACKUP_LIST=%~dp0listbackup.txt"
:: Кодировка списка - доступные варианты: UTF-8, WIN, DOS
SET "LIST_CHARSET=DOS"
::Тип бэкапа: DAY, WEEK, MONTH, YEAR
::День недели число
::1 - Воскресенье
::2 - Понедельник
::3 - Вторник
::4 - Среда
::5 - Четверг
::6 - Пятница
::7 - Суббота
:: День недели бэкап которого считается недельным
SET "WEEK_DAY_BACKUP=1"
:: Бэкап последнего числа месяца считается месячным
:: Бэкап последнего числа года считается годовым
:: Количество хранимых страховых копий по типам
SET "REZERV_DAY=6"
SET "REZERV_WEEK=5"
SET "REZERV_MONTH=11"
SET "REZERV_YEAR=50"
:: ПРИМЕЧАНИЕ: имя архива будет иметь маску:
:: %SOURCE_NAME%_ГГГГ_ММ_ДД_%TYPE_BACKUP%.7z
ECHO.
ECHO %DATE% - %TIME:~0,5% Резервное копирование:
ECHO тело скрипта: "%~0"
ECHO список: "%BACKUP_LIST%"
CALL :BACKUP_PATHS
CALL :SYS_TYPE
CALL :DATE_SET
CALL :ARC
CALL :REZERV_TRIM
ENDLOCAL
GOTO :EOF
:SYS_TYPE
:: Определение разрядности системы для использования нужной версии архиватора
ECHO "%PROCESSOR_ARCHITECTURE%""%PROCESSOR_ARCHITEW6432%"|1>NUL 2>NUL FIND /I "AMD64"&&SET "ARC_DIR=%~dp0X64"||SET "ARC_DIR=%~dp0X32"
:: Отбрасывание последнего символа "\" в пути архиватора
SET "LAST_CHAR=%ARC_DIR:~-1%"
IF "%LAST_CHAR%"=="\" SET "ARC_DIR=%ARC_DIR:~0,-1%"
IF NOT EXIST "%ARC_DIR%\7z.exe" (
ECHO Не обнаружен архиватор по пути "%ARC_DIR%"!
ECHO Положите соответсвующую версию 7z.exe по пути .\X64 или .\X86 и перезапустите скрипт!
CALL :ERROR 1
)
GOTO :EOF
:BACKUP_PATHS
:: Отбрасывание последнего символа "\" в пути бэкапа
SET "LAST_CHAR=%BACKUP_DIR:~-1%"
IF "%LAST_CHAR%"=="\" SET "BACKUP_DIR=%BACKUP_DIR:~0,-1%"
:: Создание целевой папки для резервного копирования с проверкой существования
IF NOT EXIST "%BACKUP_DIR%" MD "%BACKUP_DIR%"
IF NOT EXIST "%BACKUP_DIR%" (
ECHO Указанная папка для создания копии недоступна!
CALL :ERROR 2
)
ECHO Резервная копия будет создана в папке %BACKUP_DIR%
GOTO :EOF
:DATE_SET
:: Определение параметров текущей даты и типа бэкапа
ECHO wscript.ECHO YEAR(DATE)^&"_"^&RIGHT(0^&MONTH(DATE),2)^&"_"^&RIGHT(0^&DAY(DATE),2)^&"_"^& DAY(DATESERIAL(YEAR(DATE),MONTH(DATE)+1,1-1))^&"_"^&WEEKDAY(DATE)^&"_"^&RIGHT(0^&hour(TIME),2)^&"_"^&RIGHT(0^&minute(TIME),2) 1>"%TEMP%\tmp.vbs"
FOR /F "TOKENS=1,2,3,4,5,6,7 DELIMS=_" %%a IN ('cscript "%TEMP%\tmp.vbs" //Nologo') DO SET "TEK_YEAR=%%a"&SET "TEK_MONTH=%%b"&SET "TEK_DAY=%%c"&SET "LAST_DAY=%%d"&SET "TEK_WEEK=%%e"&SET "TEK_HOUR=%%f"&SET "TEK_MINUTE=%%g"
IF EXIST "%TEMP%\tmp.vbs" DEL "%TEMP%\tmp.vbs"
SET "TYPE_BACKUP=DAY"
IF "%WEEK_DAY_BACKUP%"=="%TEK_WEEK%" SET "TYPE_BACKUP=WEEK"
IF "%TEK_DAY%"=="%LAST_DAY%" SET "TYPE_BACKUP=MONTH"
IF "%TEK_MONTH%"=="12" (IF "%TEK_DAY%"=="%LAST_DAY%" (SET "TYPE_BACKUP=YEAR"))
CALL SET "REZERV_NUM=%%REZERV_%TYPE_BACKUP%%%"
SET "ARC_NAME=%SOURCE_NAME%_%TEK_YEAR%_%TEK_MONTH%_%TEK_DAY%~%TYPE_BACKUP%"
IF EXIST "%BACKUP_DIR%\%ARC_NAME%.7z" (
ECHO Резервная копия за этот день уже создана!
ECHO Удалите или переименуйте ее и запустите скрипт повторно!
CALL :ERROR 3
)
GOTO :EOF
:ARC
IF EXIST "%ARC_DIR%\7z.exe" (
1>nul "%ARC_DIR%\7z.exe" a -t7z "%BACKUP_DIR%\%ARC_NAME%.7z" @"%BACKUP_LIST%" -ms -mmt -mx7 -bd -scs%LIST_CHARSET% -ssw
ECHO Страховая копия создана...
)
GOTO :EOF
:REZERV_TRIM
ECHO Удалены устаревшие резервные копии:
FOR /F "SKIP=%REZERV_NUM% USEBACKQ TOKENS=1 DELIMS=" %%a IN (`DIR /O:-N /B "%BACKUP_DIR%\%SOURCE_NAME%_20??_??_??~%TYPE_BACKUP%.7z"`) DO (
DEL /Q /F "%BACKUP_DIR%\%%a"
ECHO "%BACKUP_DIR%\%%a"
)
GOTO :EOF
:ERROR
ECHO Произошло досадное недоразумение - резервная копия не создана ...
ENDLOCAL
EXIT %~1

В случае необходимости ведения лога перенаправьте информационные сообщения скрипта в файл.

Файлы: 

Чтение данных из реестра в переменную окружения

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

@ECHO OFF
CLS
:: 1-й параметр = раздел реестра для чтения
:: 2-й параметр = имя считываемого параметра - указать пустые кавычки для чтения параметра "По умолчанию"
:: 3-й параметр = имя переменной окружения куда считываем результат
:: Пример чтения именованного параметра:
CALL :REG_READ "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" "USERINIT" "MY_VAR1"
ECHO Именованный параметр значение "%MY_VAR1%"
ECHO Именованный параметр тип "%MY_VAR1_TYPE%"
:: Пример чтения безымянного параметра "По умолчанию"
CALL :REG_READ "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" "" "MY_VAR2"
ECHO Параметр "По умолчанию" значение "%MY_VAR2%"
ECHO Параметр "По умолчанию" тип "%MY_VAR2_TYPE%"
GOTO :EOF
:REG_READ
IF NOT "%~2"=="" (
FOR /F "USEBACKQ TOKENS=* DELIMS=" %%a IN (`REG QUERY "%~1" /v "%~2" 2^>NUL ^|FINDSTR /I /B /C:" %~2" 2^>NUL`) DO CALL :TRANSLATE "%%a" "%~2" "%~3"
1>NUL 2>&1 REG QUERY "%~1" /v "%~2"||(SET "%~3_TYPE="&SET "%~3=!")
)
IF "%~2"=="" (
FOR /F "USEBACKQ TOKENS=* DELIMS=" %%a IN (`REG QUERY "%~1" /ve 2^>NUL ^|FINDSTR /B /C:" " 2^>NUL`) DO CALL :TRANSLATE "%%a" "" "%~3"
1>NUL 2>&1 REG QUERY "%~1" /ve||(SET "%~3_TYPE="&SET "%~3=!")
)
CALL SET "%~3=%%%~3:~0,-1%%"
GOTO :EOF
:TRANSLATE
SET "TEMP_STR=%~1"
IF NOT "%~2"=="" CALL SET "TEMP_STR=%%TEMP_STR:*%~2=%%"
CALL SET "TEMP_STR=%%TEMP_STR:*REG_=%%"
FOR /F "USEBACKQ TOKENS=1*" %%a IN ('"%TEMP_STR%"') DO (
SET "%~3_TYPE=REG_%%~a"
SET "%~3=%%~b"
)
GOTO :EOF

Добавлена возможность чтения из реестра параметра "По-умолчанию".
Проверена работа на WinXP, Win7, Win7x64.
Предполагается что будет корректно работать на всех системах начиная с WinXP и до Win8 включительно.
Не учитывается  ненативный запуск - то есть если на x64 вызвать cmd-скрипт из x86-окружения то подмена HKLM\SOFTWARE\ на HKLM\SOFTWARE\Wow6432Node\ произойдет без вашего желания. Прямой же запуск скрипта ВСЕГДА отрабатывает в нативном окружении.

ЗЫ - Что делать с "(значение параметра не задано)" на системах Win7(судя по всему Vista и старше) для пустого параметра "По умолчанию" я пока в универсальном виде не придумал. Такое значение автоматически присваивается неописанному пустому параметру и, к сожалению, оно зависимо от языка системы.