← All posts tagged cmd

pc
cmd for token перебрать токены в строке разделенные символом :

пример вызова: test.cmd test1:test2:test3

@Echo Off
set line=%1
:loop
for /f "tokens=1* delims=:" %%a in ("%line%") do (
echo %%a
set line=%%b
)
if not "%line%" == "" goto :loop
pc
cmd taasklist cmd: tasklist "по-русски"Нужно было написать батник. В локализованной версии оказалось не так просто установить фильтр для параметра "/FI". Система радовала сообщением "Ошибка: Фильтр поиска не опознан", не смотря на параметры взятые из справки.

Запишу что удалось найти ) Тестировал на XP SP3 Rus и на Server 2003 Rus.

Формат: TASKLIST /FI "USERNAME ne NT AUTHORITY\SYSTEM" /FI "STATUS eq running"

ХР:

STATUS = Состояние. Пример: tasklist /svc /fi "Состояние ne running"
IMAGENAME = IMAGENAME
PID = ID процесса. Пример: tasklist /fi "ID Процесса eq 3364"
SESSION = Сеанс. Пример: tasklist /fi "Сеанс eq 0"
SESSIONNAME = SESSIONNAME
CPUTIME = ???
MEMUSAGE = MEMUSAGE
USERNAME = Пользователь. Пример: tasklist /v /fi "Пользователь ne user"
SERVICES = Службы. Пример: tasklist /svc /fi "Службы ne spooler"
WINDOWTITLE = WINDOWTITLE
MODULES = Модули. Пример: tasklist /m /fi "Модули ne kernel32.dll"

2003:

STATUS = Состояние. Пример: tasklist /svc /fi "Состояние ne running"
IMAGENAME = Имя образа. Пример: tasklist /fi "Имя образа eq csrss.exe"
PID = PID
SESSION = ???
SESSIONNAME = Имя сеанса. Пример: tasklist /fi "Имя сеанса eq name"
CPUTIME = ???
MEMUSAGE = Память. Пример: tasklist /fi "Память eq 0"
USERNAME = Пользователь. Пример: tasklist /v /fi "Пользователь ne user"
SERVICES = Службы. Пример: tasklist /svc /fi "Службы ne spooler"
WINDOWTITLE = ???
MODULES = Модули. Пример: tasklist /m /fi "Модули ne kernel32.dll"
pc
psexec xp cmd 2000 W7 *vista *remote *deploy

@echo off
:: ============================================================================
:: Запуск psexec с разными ключами в зависимости от версии OS 2000/XP/Vista/W7
:: ============================================================================
:: 5.0 — 2000
:: 5.1 — XP
:: 6.0 — Vista
:: 6.1 — w7
:: (c) cp 17.12.2010
:: ============================================================================
OsVer="Unknow"
wmic /node:"%1" OS get Version > "%temp%\osver.txt"

type "%temp%\osver.txt" | find "5.0"
if ERRORLEVEL 1 goto next1
set OsVer=2000
:next1

type "%temp%\osver.txt" | find "5.1"
if ERRORLEVEL 1 goto next2
set OsVer=XP
:next2

type "%temp%\osver.txt" | find "6.0"
if ERRORLEVEL 1 goto next3
set OsVer=Vista
:next3

type "%temp%\osver.txt" | find "6.1"
if ERRORLEVEL 1 goto next4
set OsVer=W7
:next4

if %OsVer% == W7 goto psexecW7
psexec \\%1 cmd
goto end
:psexecW7
psexec \\%1 -i 1 cmd
:end
pc
help cmd Как определить имя каталога, в котором находится запущенный командный файл?
Иногда сценарию надо знать полный путь к себе самому и/или к каталогу, в котором он находится. Это может понадобиться по разным причинам. Например, он должен достать из системы контроля версий исходники в каталог <script-dir>/src рядом с собой. Или, запускаются тесты из каталога <script-dir>/tests, и перед их запуском надо добавить каталог <script-dir>/bin в переменную PATH.

Можно, конечно, рассчитывать на то, что командный файл был вызван из того же каталога, где он находится, и тогда в качестве вышеупомянутого <script-dir> можно использовать переменную окружения %CD% — полный путь к текущему каталогу. Однако любые допущения в нашем деле недопустимы (хороший каламбур, однако!). Поэтому приведу более надежное решение.

Прежде всего, вспоминаем, что переменная %0 в bat-файле соответствует нулевому аргументу командной строки, т.е. имени самого файла. После этого читаем скудную документацию для команды call:

call /?



и обнаруживаем, что при использовании нумерованных переменных %0-%9 можно использовать некоторые модификаторы:

%~1 — разворачивает %1, удаляя кавычки (")
%~f1 — разворачивает %1 в полный квалифицированный путь
%~d1 — разворачивает %1 в букву диска
%~p1 — разворачивает %1 в путь
%~n1 — разворачивает %1 в имя файла
%~x1 — разворачивает %1 в расширение файла
%~s1 — развернутый путь будет содержать только короткие имена
%~a1 — разворачивает %1 в атрибуты файла
%~t1 — разворачивает %1 в дату/время создания файла
%~z1 — разворачивает %1 в размер файла
%~$PATH:1 — Ищет в каталогах, перечисленных в переменной среды PATH,
и разворачивает %1 в полное квалифицированное имя
первого совпадения. Если имя перменной среды
не определено, или если файл не найден, этот
модификатор вернет пустую строку



и, более того:

Модификаторы можно объединять для получения сложных результатов:

%~dp1 — разворачивает %1 в букву диска и путь
%~nx1 — разворачивает %1 в имя файла с расширением
%~dp$PATH:1 — ищет %1 в каталогах, перечисленных в переменной
среды PATH, и разворачивает в букву диска
и путь к первому найденному файлу.
%~ftza1 — разворачивает %1 в строку, подобную DIR



Таким образом, правильным будет использовать в качестве тега <script-dir> сочетание %~dp0, которое будет раскрыто в полный путь к каталогу, где находится сценарий. Например,

"%~dp0\packagebin.exe" --recursive-search=yes --files-mask=exe,dll,pdb,obj ^
--archive-type=zip --archive-level=max --deliver-method=ftp ^
--deliver-target=ftp://ftp.site.com --deliver-source="%~dp0\bin"



Обратите внимание на использование кавычек — потенциально каталог может иметь в своем пути пробел. Кавычки избавят от проблем в этом случае.
pc
cmd UNC forfiles ::BATCH FILE FOR DELETE OLD FILES BY LAST ACCESS DATE
::AUTHOR "Nicolas Brousse"
@ECHO OFF

:: FIRST ARGS MUST BE THE PATH TO THE DIRECTORY TO PURGE
:: SECOND ARGS MUST BE A NUMBER OF DAYS
IF [%1] == [] ( GOTO :MISSING ) ELSE ( SET PURGE_DIR=%1 )
IF [%2] == [] ( GOTO :MISSING ) ELSE ( SET DAY_LIMIT=%2 )

:: WE GET THE PC LOCAL DATE DELIMITER (contrib from Mike Bikoulis)
FOR /F "skip=4 tokens=3" %%y IN ('REG QUERY "HKCU\Control Panel\International" /v sDate') DO (
SET DATE_DELIM=%%y
)

:: WE CHECK THE PC LOCAL SHORT DATE FORMAT
FOR /F "skip=4 tokens=2* delims= " %%y IN ('REG QUERY "HKCU\Control Panel\International" /v sShortDate') DO (
IF NOT "%%z" == "dd%DATE_DELIM%MM%DATE_DELIM%yyyy" GOTO :DATEFORMAT
)

:: SET CURRENT DATE MINUS DAYS ARGUMENT
SET YEAR=%DATE:~6,4%
SET MONTH=%DATE:~3,2%
SET DAY=%DATE:~0,2%

IF %MONTH:~0,1% EQU 0 ( SET MONTH=%MONTH:~1,1% )
IF %DAY:~0,1% EQU 0 ( SET DAY=%DAY:~1,1% )

SET /A LIMIT_UNIX_TIMESTAMP = (((%YEAR% 365) + (%MONTH% 31) + %DAY%) 24 60 ) — ( %DAY_LIMIT% 24 60 )

:: PARSE THE DIRECTORY TO PURGE THEN CHECK FILES ON THEIR LAST ACCESS DATE
FOR /F "usebackq delims=" %%a IN (`DIR /A:-D /B /S %PURGE_DIR%`) DO (
SET CURRENT_FILE=%%a
IF EXIST "%%a" (

ECHO ---------------------------------------------------------
ECHO TEST "%%a"

FOR /F "usebackq skip=5 tokens=1" %%b IN (`DIR /T "%%a"`) DO (
CALL :TESTSTRING %%b
)
)
)

GOTO :END

:: GET FILE LAST ACCESS DATE
:TESTSTRING
FOR /F "tokens=1-3 delims=%DATE_DELIM%" %%c IN ("%1") DO (
IF NOT [%%e] == [] (
CALL :TESTDATE %%e %%d %%c
)
)
GOTO :END

:: TEST DATE WITH LIMIT_UNIX_TIMESTAMP
:: DELETE TOO OLD FILES, WE COULD DO AN ERASE BUT IT'S LESS SECURE
:TESTDATE

SET YEAR=%1
SET MONTH=%2
SET DAY=%3

IF %MONTH:~0,1% EQU 0 ( SET MONTH=%MONTH:~1,1% )
IF %DAY:~0,1% EQU 0 ( SET DAY=%DAY:~1,1% )

SET /A FILE_UNIX_TIMESTAMP = ((%YEAR% 365) + (%MONTH% 31) + (%DAY% 1 )) 24 * 60

ECHO FILE_UNIX_TIMESTAMP = %FILE_UNIX_TIMESTAMP%
ECHO LIMIT_UNIX_TIMESTAMP = %LIMIT_UNIX_TIMESTAMP%

IF %FILE_UNIX_TIMESTAMP% LSS %LIMIT_UNIX_TIMESTAMP% (
IF EXIST "%CURRENT_FILE%" (
ECHO DELETE "%CURRENT_FILE%"
DEL /Q /F "%CURRENT_FILE%"
)
)

GOTO :END

:MISSING
ECHO USE : %0 [PATH] [DAYS]
GOTO :END

:DATEFORMAT
ECHO THIS PC HAS MUST HAVE A SHORT DATE FORMAT LIKE dd%DATE_DELIM%MM%DATE_DELIM%yyyy
GOTO :END

:END