скрытые возможности пакетных файлов windows

<p>каковы некоторые из менее известных, но важных и полезных функций пакетных файлов windows?</p><p>методические рекомендации:</p><ul> <li>одна особенность за ответ</li> <li>дайте краткое <strong> описание </strong> функции и <strong> пример </strong>, а не только ссылка на документацию</li> <li>ограничение ответов на <strong> встроенную функциональность </strong>, т. е. не требует дополнительного программного обеспечения, такого как <em> windows resource kit </em></li> </ul><p>пояснение: мы ссылаемся здесь на сценарии, которые обрабатываются cmd.exe, который является вариантом по умолчанию для вариантов winnt.</p><p>(смотрите также: <a href="https://stackoverflow.com/questions/148968/windows-batch-files-bat-vs-cmd">пакетные файлы windows: .bat против .cmd?</a> )</p>

<p>продолжение строки:</p><pre><code>call c:\windows\system32\ntbackup.exe ^ backup ^ /v:yes ^ /r:no ^ /rs:no ^ /hc:off ^ /m normal ^ /l:s ^ @daily.bks ^ /f daily.bkf </code></pre>

<pre><code>pushd path </code></pre><p>перемещает вас в каталог, указанный <em>путь</em>.</p><pre><code>popd </code></pre><p>возвращает вас в каталог, из которого вы "нажали".</p>

<p>не уверен, насколько это полезно в файле <em>batch</em>, но эту команду очень удобно использовать в командной строке:</p><pre><code>c:\some\_directory> start . </code></pre><p>это откроет windows explorer в папке "some\_directory".</p><p>я нашел это очень экономит время.</p>

<p>мне всегда было трудно читать комментарии, помеченные ключевым словом в каждой строке:</p><pre><code>rem blah blah blah </code></pre><p>легче читать:</p><pre><code>:: blah blah blah </code></pre>

<p>переменные подстроки:</p><pre><code>> set str=0123456789 > echo %str:~0,5% 01234 > echo %str:~-5,5% 56789 > echo %str:~3,-3% 3456 </code></pre>

<p> <a href="http://www.robvanderwoude.com/ntfor.html">команда for</a> ! хотя я ненавижу писать командные файлы, я благодарен за это.</p><pre><code>for /f "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k </code></pre><p>будет анализировать каждую строку в myfile.txt, игнорируя строки, начинающиеся с точки с запятой, передавая 2-й и 3-й токены из каждой строки в тело for, с токенами, разделенными запятыми и/или пробелами. обратите внимание, что операторы body ссылаются на% i, чтобы получить 2-й токен,% j, чтобы получить 3-й токен, и% k, чтобы получить все оставшиеся токены после 3-го.</p><p>вы также можете использовать это для перебора каталогов, содержимого каталогов и т.д.</p>

<p>вместо того, чтобы засорять скрипт с помощью rem или :: строк, я делаю следующее в верхней части каждого скрипта:</p><pre><code>@echo off goto :start description of the script. usage: myscript -parm1|parm2 > result.txt :start </code></pre><p>обратите внимание, как вы можете использовать символы канала и перенаправления, не экранируя их.</p>

<p>путь (с диском), где находится скрипт: ~ dp0</p><pre><code>set bat\_home=%~dp0 echo %bat\_home% cd %bat\_home% </code></pre>

<p>часть% ~ dp0 уже упоминалась, но на самом деле есть еще кое-что: символы после ~ определяют извлекаемую информацию.<br> отсутствие буквы приводит к возврату имени файла патча<br> d - возвращает букву диска<br> p - возвращает путь<br> s - возвращает короткий путь<br> x - возвращает расширение файла<br> таким образом, если вы выполните скрипт test.bat ниже из папки c:\temp\long dir name \,</p><pre><code>@echo off echo %0 echo %~d0 echo %~p0 echo %~dp0 echo %~x0 echo %~s0 echo %~sp0 </code></pre><p>вы получите следующий вывод</p><blockquote> <pre><code>test c: \temp\long dir name\ c:\temp\long dir name\ .bat c:\temp\longdi~1\test.bat \temp\longdi~1\ </code></pre></blockquote><p>и если параметр передается в ваш скрипт, как в<br> test c:\temp\mysrc\test.cpp<br> те же манипуляции можно выполнить с переменной% 1.</p><p>но результат расширения% 0 зависит от местоположения!<br> на "верхнем уровне" пакета оно расширяется до текущего имени файла пакета.<br> в функции (вызове) она расширяется до имени функции.</p><pre><code>@echo off echo %0 call :test goto :eof :test echo %0 echo %~0 echo %~n0 </code></pre><p>выход (пакетный файл запускается с mybatch.bat)</p><pre><code>mybatch.bat :test :test mybatch </code></pre>

<p>используя call, exit/b, setlocal & endlocal, вы можете реализовать подпрограммы с локальными переменными.</p><p>пример:</p><pre><code>@echo off set x=xxxxx call :sub 10 echo %x% exit /b :sub setlocal set /a x=%1 + 1 echo %x% endlocal exit /b </code></pre><p>это напечатает</p><pre><code>11 xxxxx </code></pre><p>хотя: sub изменяет x.</p>

<p>подлый трюк с ожиданием n секунд (не является частью cmd.exe, но не является дополнительным программным обеспечением, поскольку он поставляется с windows), см. строку ping. вам нужно n + 1 пингов, так как первый пинг проходит без задержки.</p><pre><code> echo %time% call :waitfor 5 echo %time% goto :eof :waitfor setlocal set /a "t = %1 + 1" >nul ping 127.0.0.1 -n %t% endlocal goto :eof </code></pre>

<p>спасаясь от "сантехники":</p><pre><code>echo ^| ^< ^> ^& ^\ ^^ </code></pre>

<p>возможность запускать команды и обрабатывать вывод (например, обратные пометки '$ ()' в bash).for /f %i in ('dir /on /b .jpg') do echo --^> %i если в именах файлов есть пробелы, используйте это:for /f "tokens=" %i in ('dir /on /b .jpg') do echo --^> %i 

создание пустого файла:> copy nul filename.ext 

чтобы скрыть весь вывод команды перенаправить на> nul 2> & 1.например, некоторые программы командной строки отображают вывод, даже если вы перенаправляете на> nul. но если вы перенаправите вывод, как показано ниже, все выходные будут подавлены.pskill notepad >nul 2>&1 правка: смотрите <a href="http://blogs.msdn.com/myocom/archive/2005/06/08/427043.aspx">игнорируя вывод команды для объяснения того, как это работает.

эквивалент bash (и других оболочек)echo -n hello # or echo helloc который выводит "hello" без завершающего символа новой строки. хак для этого:<nul set /p any-variable-name=hello set /p - это способ предложить пользователю ввести данные. он выдает заданную строку и затем ждет (на той же строке, то есть crlf), чтобы пользователь набрал ответ.<nul просто передает пустой ответ на команду set /p, так что в результате получается строка запроса. (используемая переменная остается неизменной из-за пустого отклика.)проблемы: невозможно вывести начальный знак равенства, а в vista начальные пробельные символы удаляются, но не в xp.

pause останавливает выполнение и отображает следующую подсказку:нажмите любую клавишу для продолжения . , ,.полезно, если вы хотите запустить пакет, дважды щелкнув его в проводнике windows, и хотите увидеть результат, а не просто всплывающее окно командной строки.

поиск и замена при установке переменных среды:> @set fname=%date:/=% ... удаляет "/" из даты для использования в именах файлов с метками времени.и подстроки тоже ...> @set dayofweek=%fname:~0,3% 

целочисленная арифметика:> set /a result=10/3 + 1 4 

разделители команд:cls & dir copy a b && echo success copy a b || echo failure во 2-й строке команда после && выполняется только в том случае, если первая команда выполнена успешно.на 3-й строке команда после || запускается только в случае сбоя первой команды.

вы можете соединять операторы if для получения эффекта, подобного короткому замыканию логического and '.if foo if bar baz 

выведите пустую строку:echo. 

если структура блока:if "%vs90comntools%"=="" ( echo: visual studio 2008 is not installed exit /b ) 

для быстрого преобразования текстового файла unicode (16 бит/символ) в файл dos ascii (8 бит/символ).c:> type unicodeencoded.txt > dosencoded.txt в качестве бонуса, если возможно, символы правильно отображаются.

не обеспечивает большой функциональности, но вы можете использовать команду title для нескольких целей, например, для предоставления статуса длинного сценария на панели задач или просто для улучшения обратной связи с пользователем.@title searching for ... :: processing search @title preparing search results :: data processing 

задержка раскрытия переменных (с подстроками, добавленными для хорошей меры): @echo off setlocal enableextensions enabledelayedexpansion set full=/u01/users/pax :loop1 if not "!full:~-1!" == "/" ( set full2=!full:~-1!!full2! set full=!full:~,-1! goto :loop1 ) echo !full! endlocal 

у вас нет удобного редактора, и вам нужно создать командный файл?copy con test.bat просто введите команды, нажмите ввод для новой строки. нажмите ctrl-z и enter, чтобы закрыть файл.

пример вычитания строки в date и time для получения файла с именем "yyyy-mm-dd hh: mm: ss.txt"<blockquote> echo test > "%date:~0,4%-%date:~5,2%-%date:~8,2% %time:~0,2%_%time:~3,2%_%time:~6,2%.txt" </blockquote>я использую color, чтобы указать, если мой сценарий завершится успешно, потерпел неудачу или нуждается в некотором вводе, меняя цвет текста и фона. это действительно помогает, когда у вас есть машина в пределах досягаемости, но довольно далеко<blockquote> цвет xy </blockquote>где x и y - шестнадцатеричное значение от 0 до f, где x - фон, y - текст, когда x = y цвет не изменится.<blockquote> цвет z </blockquote>меняет цвет текста на "z" и устанавливает черный фон, "цвет 0" не будет работатьдля названий цветов звоните<blockquote> цвет ? </blockquote>

полный контроль над выводом с пробелами и escape-символами .:echo. ^<resourcedir^>/%basedir%/resources^</resourcedir^> 

thesoftwarejedi уже упомянул команду for, но я собираюсь упомянуть ее еще раз, поскольку она очень мощная.ниже выводится текущая дата в формате ггггммдд, я использую ее при создании каталогов для резервных копий.for /f "tokens=2-4 delims=/- " %a in ('date/t') do echo %c%b%a 

вы можете использовать call для оценки имен позже, что приведет к некоторым полезным свойствам.call set someenvvariable_%extension%=%%%somevalue%%% использование вызова для установки переменных, имена которых зависят от других переменных. при использовании с некоторыми правилами именования переменных вы можете эмулировать коллекции данных, такие как массивы или словари, используя осторожные правила именования. тройной% около somevalue таков, что он будет оценивать одно имя переменной, окруженное одиночными% после вызова и до вызова set. это означает, что два% подряд переходят к одному символу%, а затем он снова его расширяет, поэтому somevalue фактически является указателем имени.call set tempvar=%%someenvvariable_%extension%%% использование его с временной переменной для получения значения, которое затем можно использовать в логике. это наиболее полезно при использовании в сочетании с отложенным расширением переменной.для правильного использования этого метода необходимо включить отложенное расширение переменной. поскольку по умолчанию он отключен, лучше всего включить его в сценарии, указав одну из первых инструкций:setlocal enabledelayedexpansion 

поиск исполняемого файла по пути (или другой похожей на путь строке, если необходимо):c:> for %i in (cmd.exe) do @echo. %~$path:i c:\windows\system32\cmd.exe c:\> for %i in (python.exe) do @echo. %~$path:i c:python25python.exe c:> 

что касается использования :: вместо rem для комментариев: будьте осторожны! :: - это особый случай метки call, которая действует как комментарий. при использовании внутри скобок, например, в цикле for или if, функция преждевременно завершает работу. очень расстраивает отладку!смотрите <a href="http://www.ss64.com/nt/rem.html">http://www.ss64.com/nt/rem.html для полного описания. (добавление в качестве нового ответа вместо комментария к <a href="https://stackoverflow.com/questions/245395/underused-features-of-windows-batch-files#245398">первое упоминание об этом выше потому что я еще не заслуживаю упоминания: 0) 

локальные переменные все еще анализируются для строки, которую использует endlocal. это учитывает уловки как:endlocal & set myglobal=%somelocal% & set myotherglobal=%someotherlocal% это полезный способ передачи результатов в вызывающий контекст. в частности,% somelocal% выходит из области действия, как только endlocal завершает работу, но к тому времени% somelocal% уже раскрывается, поэтому myglobal назначается в контексте вызова с локальной переменной.по той же причине, если вы решили сделать:endlocal & set mylocal=%mylocal% вы обнаружите, что теперь ваша новая переменная mylocal фактически является обычной переменной среды вместо локализованной переменной, которую вы, возможно, и предполагали.

в наши дни многие люди используют goto: eof для завершения своих командных файлов, но вы также можете использовать exit/b для этой цели.преимущество использования exit/b состоит в том, что вы можете добавить уровень ошибки после exit/b, и он выйдет с этим уровнем ошибки.

режим быстрого редактирования в cmd.exe - мой любимый. это немного не по теме, но при взаимодействии с командой shell это может быть спасением. нет, я не гиперболичен - вы увидите только <strong>caret-capitol-v</strong> определенное количество раз, прежде чем умрете; чем больше ты видишь, тем быстрее ты умрешь. откройте regedit (осторожно, не моя вина, синий экран и т.д.) перейти к hkcu/консоль установите quickedit на 1 (вы также можете установить это с помощью пользовательского интерфейса, что, вероятно, является лучшим способом. см. комментарии для получения инструкций. также есть хороший однострочный скрипт для этого.)теперь, чтобы скопировать, просто щелкните левой кнопкой мыши и перетащите, чтобы выбрать, и щелкните правой кнопкой мыши, чтобы скопировать. чтобы вставить, просто щелкните правой кнопкой мыши.нет больше ^ v ^ v ^ v ^ v ^ v ^ v ^ v ^ v ^ v ^ v ^ v ^ v ^ v ^ v !!!, я думаю, что просто кого-то убил. сожалею!

call set - расширяет переменные окружения на несколько уровней.нашел это по адресу <a href="http://ss64.com/nt/call.html#advanced">http://ss64.com/nt/call.html#advanced из ответа на другой вопрос so <a href="https://stackoverflow.com/questions/691047/batch-file-variables-initialized-in-a-for-loop">переменные пакетного файла инициализированы в цикле for set varname=param set param=this call set answer=%%%varname%%% echo %answer% даетset varname=param set param=this call set answer=%param% echo this this 

подпрограммы (выходы 42): @echo off call :answer 42 goto :eof :do_something echo %1 goto :eof и подпрограммы, возвращающие значение (выходные данные 0, 1, 2 и т. д.): @echo off setlocal enableextensions enabledelayedexpansion call :seq_init seq1 :loop1 if not %seq1%== 10 ( call :seq_next seq1 echo !seq1! goto :loop1 ) endlocal goto :eof :seq_init set /a "%1 = -1" goto :eof :seq_next set /a "seq_next_tmp1 = %1" set /a "%1 = %seq_next_tmp1% + 1" set seq_next_tmp1= goto :eof 

опция подкаталога "удалить каталог":rd /s /q junk 

перенаправление вывода на консоль, даже если вывод пакета уже перенаправлен в файл с помощью синтаксиса > con.пример: foo.cmd:echo a echo b > con вызов:foo.cmd > output.txt это приведет к тому, что "a" перейдет к output.txt, а "b" пойдет на консоль.

shift это способ перебора переменного количества аргументов, передаваемых в сценарий (или подпрограмму) в командной строке. в простейшем случае он смещает% 2 на% 1,% 3 на% 2 и т.д. (вы также можете передать параметр в shift, чтобы пропустить несколько аргументов.) это делает команду "деструктивной" (т. е.% 1 исчезает навсегда), но позволяет избежать жесткого кодирования максимального количества поддерживаемых аргументов.вот краткий пример обработки аргументов командной строки по одному::parseargs if "%1"=="" ( goto :doneparsingargs ) rem ... do something with %1 ... shift goto :parseargs :doneparsingargs rem ... 

вы можете использовать уровень ошибки, чтобы проверить, доступна ли данная программа в системе (текущий каталог или путь), где будет запускаться ваш пакетный файл. чтобы это работало, программа, которую вы тестируете, должна быть запущена, завершена и установить код выхода, когда это произойдет. в примере я использую -? как аргумент для myexe, большинство программ cli имеют похожий аргумент, такой как -h, --help, -v и т. д. ... это гарантирует, что он просто запускается и выходит, оставляя или устанавливая уровень ошибки 0myexe -? >nul 2>&1 set errcode=%errorlevel% @if %errcode% equ 0 ( echo myexe -? does not return an error (exists) ) else ( echo myexe -? returns an error (does not exist) ) да, вы можете проверить уровень ошибки напрямую, а не присваивать его errcode, но таким образом вы можете иметь команды между тестом и условием, и вы будете проверять условие повторно при необходимости.

получить текущий день, месяц и год (независимо от локали):for /f "tokens=1-4 delims=/-. " %%i in ('date /t') do (call :set_date %%i %%j %%k %%l) goto :end_set_date :set_date if ("%1:~0,1%" gtr "9") shift for /f "skip=1 tokens=2-4 delims=(-)" %%m in ('echo,^|date') do (set %%m=%1&set %%n=%2&set %%o=%3) goto :eof :end_set_date echo day in 'dd' format is %dd%; month in 'mm' format is %mm%; year in 'yyyy' format is %yy% 

правильный формат для циклов с числовыми переменнымиfor /l %%i in (startnumber, counter, endnumber) do echo %%i подробнее> <a href="http://www.ss64.com/nt/for.html">http://www.ss64.com/nt/for.html 

команда <a href="http://www.ss64.com/nt/choice.html">choice запрашивает у пользователя один из нескольких вариантов (нажатием одной клавиши)@echo off echo please choose one of the following options echo 1. apple echo 2. orange echo 3. pizza echo a, b, c. something else choice /c:123abc /m "answer?" set choicelevel=%errorlevel% echo choice was: %choicelevel% %choicelevel% будет выбранной n-й опцией (в приведенном выше примере b=5).более подробная информация на <a href="http://www.ss64.com/nt/choice.html">выбор справочной странице <a href="http://www.ss64.com/nt/">ss64.com .

удобный трюк, когда вы хотите скопировать файлы между ветками:c:srcbranch1mydirmydir2mydir3mydir4>xcopy %cd:branch1=branch2%foo overwrite c:srcbranch1mydirmydir2mydir3mydir4foo.txt (yes/no/all)? y c:srcbranch2mydirmydir2mydir3mydir4foo.txt при этом используется как переменная среды% cd%, так и подстановка переменных среды.

для синтаксического анализа <strong>stdin</strong> внутри скрипта вам понадобится этот трюк с командами for и find:for /f "tokens=" %%g in ('find /v ""') do ( :: do what you want with %%g echo %%g ) 

массивы в пакетных файлах.установите значение:set count=1 set var%count%=42 извлеките значение в командной строке:call echo %var%count%% извлеките значение в пакетном файле:call echo %%var%count%%% обратите внимание на дополнительные знаки%.техника может выглядеть немного волосатой, но она весьма полезна. выше будет напечатано содержимое  var1  (т.е. 42), как мы объяснили. мы также можем заменить команду <strong>echo</strong> на <strong>set</strong>, если мы хотим установить другую переменную в значение  var1 . это означает, что следующее является допустимым назначением в командной строке:call set x=%var%count%% затем, чтобы увидеть значение  va1 :echo %x% 

/ с параметр для самого cmd.exe, говорит ему, чтобы он запустился и затем выполнил эти команды.раньше я часто делал:победа + г, cmd вернуть, пинг google.com вернутьно сейчас я просто делаю:победа + г, cmd/c ping google.com вернутьнамного быстрее. также полезно, если вы используете pstools и хотите использовать psexec для выполнения некоторых функций командной строки на удаленном компьютере.правка: / к работает так же, но оставляет подсказку открытой. это может пригодиться чаще.

 <a href="http://technet.microsoft.com/nl-nl/library/cc753551%28ws.10%29.aspx">forfiles очень полезен, например, для рекурсивного удаления всех файлов старше двух днейforfiles /d -2 /p "c:temp" /s /c "cmd /c del @path" 

что бы это ни стоило, <a href="http://ss64.com/nt/">это - неплохой онлайн-справочник по windows cmd или пакетным файлам. я узнал несколько вещей, которые я не знал из этого.

доски макрос.я давно потерял ссылку на это, но я все еще думаю, что это хорошая идея, и стоит поделиться.мы можем объединить пакетные файлы и скрипты doskey в один файл. это может показаться слишком умным, но это работает.;= @echo off ;= rem call doskey and use this file as the macrofile ;= %systemroot%system32doskey /listsize=1000 /macrofile=%0% ;= rem in batch mode, jump to the end of the file ;= goto end ;= doskey aliases h=doskey /history ;= file listing enhancements ls=dir /x $* ;= directory navigation up=cd .. pd=pushd ;= :end ;= rem ****************************************************************** ;= rem * eof - don't remove the following line. it clears out the ';' ;= rem * macro. were using it because there is no support for comments ;= rem * in a doskey macro file. ;= rem ****************************************************************** ;= </code></pre><p>он работает путем определения поддельного макроса doskey ';' который изящно (или тихо) игнорируется, когда он интерпретируется как пакетный файл.</p><p>я сократил версию, указанную здесь, если вы хотите больше, перейдите <a href="http://ben.versionzero.org/wiki/doskey\_macros">здесь</a> .</p>

<p>использование pushd к пути unc создаст временное сопоставление диска (начиная с z и переместившись назад, чтобы найти следующую доступную букву) и поместит вас в этот диск и путь. когда вы попадаете или выходите из командной строки, временное сопоставление исчезает.</p><pre><code> c:\>pushd \\yourmom\jukebox z:\>pushd \\yourmom\business y:\> </code></pre><p>кроме того, не столько совет по пакетам, сколько совет по среде командной строки, но когда вы работаете в командной строке с pushd и popd и сетевыми ресурсами, полезно модифицировать ваш prompt с помощью $ + (глубина показа pushd стека) и $ m (показать путь к сетевому ресурсу).</p><pre><code> c:\utils>prompt $+$m$p$g c:\utils>pushd m: +\\yourmom\pub m:\>pushd c:\ ++c:\>pushd m:\ c:\utils ++c:\>popd +\\yourmom\pub m:\>popd c:\utils> </code></pre>

<p>я считаю, что простота, с которой вы можете перенаправить вывод команд в файлы, чрезвычайно полезна:</p><pre><code>dir *.txt > tmp.txt dir *.exe >> tmp.txt </code></pre><p>одиночная стрелка создает или перезаписывает файл, к нему добавляется двойная стрелка. теперь я могу открыть tmp.txt в моем текстовом редакторе и делать разные полезные вещи.</p>

<p>findstr с поддержкой регулярных выражений:</p><pre><code>findstr "^[0-9].*" c:\windows\system32\drivers\etc\hosts </code></pre>

<p>найти строки в файлах в папке с помощью канала '|' команда:</p><pre><code>dir /b *.* | findstr /f:/ "thepattern" </code></pre>

<p>встроенные комментарии, используя <code>&::</code>.</p><pre><code>:: this is my batch file which does stuff. copy thisstuff thatstuff &:: we need to make a backup in case we screw up! :: ... do lots of other stuff </code></pre><p>как это работает? это безобразный хак. <code>&</code> - это разделитель команд, приблизительно аппроксимирующий <code>;</code> оболочек unix. <code>::</code> - это еще один уродливый хак, который своего рода подражает эмуляции оператора <code>rem</code>. конечный результат заключается в том, что вы выполняете свою команду, а затем выполняете команду "ничего не делать", что приближает комментарий.</p><p>это работает не во всех ситуациях, но работает достаточно часто, чтобы быть полезным хаком.</p>

<p>список всех дисков:</p><pre><code>fsutil fsinfo drives </code></pre>

<p>установка переменных среды из файла с помощью <code>set /p</code></p><pre><code>set /p svnversion=<ver.tmp </code></pre>

<p>позволяет изменять каталог на основе переменной среды без указания директивы '%'. если указанная переменная не существует, попробуйте имя каталога.</p><pre><code>@if defined %1 (call cd "%%%1%%") else (call cd %1) </code></pre>

<p>добавить файлы используя copy:</p><pre><code>copy file1.txt+file2.txt+file3.txt append.txt </code></pre><p>также, чтобы установить все параметры cli в одну переменную:</p><pre><code>set msg=%* </code></pre><p>это займет каждое слово (или символ), разделенные пробелами, и сохранит его в одну переменную пакетного файла. технически, каждый параметр - это% 1,% 2, $ 3 и т.д., но эта команда set использует подстановочный знак для ссылки на каждый параметр в stdin.пакетный файл:@set msg=% @echo %msg% командная строка:c:test>test.bat hello world! hello world! 

создать и начать редактирование нового файлаcopy con new.txt this is the contents of my file ^z ctrl + z отправляет символ ascii eof. это как heredocs в bash:cat <<eof > new.txt this is the contents of my file eof 

символические ссылки:mklink /d directorylink ..realdirectory mklink filelink realfile эта команда является родной для windows server 2008 и более поздних версий, включая vista и windows 7. (она также включена в некоторые наборы ресурсов windows).

рекурсивно искать строку в дереве каталогов:findstr /s /c:"string literal" . вы также можете использовать регулярные выражения:findstr /s /r "^error" .log рекурсивный поиск файлов:dir /s myfile.txt 

goto: eof картоня добавляю "goto: eof" в конец моих скриптов как удобное место для фрагментов кода. таким образом, я могу быстро скопировать/вставить в эту область и из нее, без необходимости комментировать/раскомментировать.goto :eof :: code scraps call this.bat call that.bat set ts=%date:~10%%date:~4,2%%date:~7,2%-%time:~0,2%%time:~3,2%%time:~6%% for /r c:temp %%g in (.bak) do del %%g 

залог по ошибке.if "%errorlevel%" neq "0" ( echo "error: something broke. bailing out." exit /b 1 ) 

как и выше, используя call, exit/b, setlocal & endlocal, вы можете реализовать функции с локальными переменными и возвращаемыми значениями.пример:@echo off set x=xxxxx call :fun 10 echo "%x%" echo "%y%" exit /b :fun setlocal set /a y=%1 + 1 endlocal & set x=%y% exit /b это напечатает:"11" "" переменная y никогда не покидает локальную область, но из-за того, как cmd разрешает одну строку за раз, вы можете извлечь значение в переменную x в родительской области.

несколько команд в одной строке, полезно во многих ситуациях:& используется для объединения двух команд, выполняет command1, а затем command2 && условная комбинация, выполняет команду2, если команда1 завершается успешно ¦¦ команда2 выполняется, только если команда1 не выполнена успешно.примеры:::  edit the most recent .txt file and exit, useful in a .cmd / .bat  for /f %%i in ('dir .txt /b /o:-n') do notepad %%i & exit ::  if exist any .txt file, display the list in notepad, if not it ::  exits without any error (note the && and the 2> error redirection) dir .txt > txt.lst 2> nul && notepad txt.lst 

метод для установки уровня ошибки на любое желаемое число:номер выхода cmd/c

скрыть ввод для интерактивного пакетного сценария: @echo off echo hp1x500p[pzbbbfh#b##fxf-v@$fpf]f3/f1/5++u5>in.com set /p secret\_password="enter password:"<nul for /f "tokens=*" %%i in ('in.com') do (set secret\_password=%%i) del in.com </code></pre>

<p>я бы сказал, что debug.exe - очень полезная и очень недоиспользуемая функция пакетных файлов.</p><p>команда debug позволяет вам ...</p><ol> <li>собрать и разобрать 16-битный код</li> <li>чтение/запись памяти (современная защищенная память делает это значительно менее полезным.)</li> <li>чтение секторов данных с жесткого диска в сыром виде</li> <li>hex edit</li> </ol><p>короче говоря, этот инструмент очень мощный. в наши дни его уже можно было бы не много использовать, но возможность вызывать и контролировать эту функцию из пакетного сценария добавляет ошеломляющее количество возможностей пакетного сценария.</p><p>примечание. microsoft удалила эту команду из 64-разрядных версий windows xp и vista и намерена полностью удалить ее из windows 7 из того, что я слышал.</p>

<p>удалить окружающие цитаты.</p><pre><code>for /f "useback tokens=*" %%a in ('%str%') do set str=%%~a </code></pre><p>мне недавно пришлось написать командный файл, который вызывается событием prebuild vs, и я хочу передать в каталог проекта в качестве параметра. в командном файле мне нужно объединить путь с именем вложенной подпапки, но сначала нужно удалить окружающую кавычку.</p>

<p>вот как построить classpath путем сканирования данного каталога.</p><pre><code>setlocal enabledelayedexpansion if defined classpath (set classpath=%classpath%;.) else (set classpath=.) for /r .\lib %%g in (*.jar) do set classpath=!classpath!;%%g echo the classpath definition is %classpath% </code></pre><p>работает в xp (или лучше). в w2k вам нужно использовать пару файлов bat для достижения того же результата (см. <a href="http://www.rgagnon.com/javadetails/java-0587.html">включить все файлы jar в определение classpath</a> ).</p><p>это не нужно для 1.6, так как вы можете указать подстановочный знак непосредственно в classpath (например, -cp ".\lib *").</p>

<pre><code>help </code></pre><p>при работе с другой версией ос важно знать, какие команды доступны изначально. ввод help в командной строке показывает, какие команды доступны, с кратким описанием того, что они делают.</p><pre><code>cmd.exe /? </code></pre><p>это перечислит все параметры командной строки для запуска командной строки, а также настройки реестра, которые изменяют поведение всей системы.</p>

<p>для циклов с числовыми счетчиками (выходы с 1 по 10):</p><pre><code>for /l %i in (1,1,10) do echo %i </code></pre>

<p>вы можете изменить командный файл во время его работы. например, вы можете добавить забытое <code>pause</code> в конец файла во время его работы, если хотите увидеть результаты до выхода пакетного файла.</p><p>смотрите <a href="https://stackoverflow.com/questions/906586/changing-a-batch-file-when-its-running">изменение командного файла при его запуске</a> </p><p>я лично думаю об этом больше как о гоче, чем как о особенности.</p>

<p>этот пакетный файл работает <strong>оба</strong> с простыми <strong>файлы</strong>, а также <strong>каталоги</strong> в качестве параметров командной строки (вы можете смешивать их в любом порядке). цикл запускает команду (в данном примере 'echo') для любого указанного файла, если параметр является каталогом, он запускает команду рекурсивно для каждого файла в нем.</p><pre><code>@echo off for /f "delims=" %%f in ('dir %* /a-d /b /s') do echo %%f </code></pre>

<p>чтобы получить текущую дату/время для файлов журналов и т.д., я использую это в своих пакетных файлах:</p><pre><code>for /f "usebackq tokens=1,2,3,4,5,6,7 delims=/:. " %%a in (`echo %date% %time%`) do set now=%%d%%b%%c\_%%e%%f%%g set log=output\_%now%.log </code></pre>

<p>команда if! без этого мой пакетный файл был хламом!</p><pre><code>@echo off if exist %windir%\system32\iexplore.exe goto end echo hmm... it seems you do not have internet explorer. echo great! you seem to understand ;) :end echo hmm... you have internet explorer. echo that is bad :) </code></pre>

<p><code>find</code> как замена для grep.<br> я взломал небольшую "телефонную книгу" для себя с помощью find. очень полезно:</p><pre><code>@echo off :begin set /p term=enter query: type phonebookfile.txt |find /i "%term%" if %errorlevel% == 0 goto :choose echo no entry found set /p new\_entry=add new entry: echo %new\_entry% >> phonebookfile.txt :choose set /p action=(q)uit, (n)ew query or (e)dit? [q] if "%action%"=="n" goto anfang if "%action%"=="e" ( notepad phonebookfile.txt goto :choose ) </code></pre><p>очень быстро и эффективно.</p>

<p>линейное исполнение</p><p>хотя в большинстве случаев это неочевидное преимущество, оно может помочь при попытке обновить объекты во время их работы. например:</p><p>updatesource.bat</p><pre><code>copy updatesource.bat current.bat echo "hi!" </code></pre><p>current.bat</p><pre><code>copy updatesource.bat current.bat </code></pre><p>теперь выполнение current.bat производит этот вывод.</p><pre><code>hi! </code></pre><p><em>осторожно</em> хотя пакетное выполнение продолжается по номеру строки. такое обновление может привести к пропуску или перемещению назад строки, если основные строки не имеют точно одинаковые номера строк.</p>

<p>при использовании <strong> расширений команд </strong> параметров оболочки в сценарии настоятельно рекомендуется выполнить следующий прием в начале сценариев.</p><p>- информация вставлена из <a href="http://www.ss64.com/nt/setlocal.html">http://www.ss64.com/nt/setlocal.html</a> </p><blockquote> <p>setlocal установит ошибку, если дан аргумент. он будет равен нулю, если указан один из двух допустимых аргументов, а один - в противном случае.</p> <p>вы можете использовать это в пакетном файле, чтобы определить, доступны ли расширения команд, используя следующую технику:</p> </blockquote><pre><code>verify errors 2>nul setlocal enableextensions if errorlevel 1 echo unable to enable extensions </code></pre><blockquote> <p>это работает, потому что "verify errors" устанавливает errorlevel в 1, а затем setlocal не сможет сбросить значение errorlevel, если расширения недоступны (например, если скрипт выполняется под command.com)</p> <p>если расширения команд постоянно отключены, setlocal enableextensions не восстановят их.</p> </blockquote>

<p>мне очень нравится эта ссылка <a href="http://www.ss64.com/nt/">windows xp commands</a> , а также ссылка <a href="http://www.ss64.com/nt/syntax.html">синтаксис</a> вверху; он охватывает многие советы и хитрости, уже найденные в других ответах.</p>

<p>при передаче неизвестного количества параметров в пакетный файл, например, когда несколько файлов перетаскиваются и помещаются в командный файл для его запуска, вы можете ссылаться на каждую переменную параметра по имени, например,.</p><pre><code>type %1 type %2 type %3 type %4 type %5 ...etc </code></pre><p>но это становится очень грязным, когда вы хотите проверить, существует ли каждый параметр:</p><pre><code>if [%1] neq [] ( type %1 ) if [%2] neq [] ( type %2 ) if [%3] neq [] ( type %3 ) if [%4] neq [] ( type %4 ) if [%5] neq [] ( type %5 ) ...etc </code></pre><p>кроме того, вы можете принять только ограниченное количество параметров с этим подходом.</p><p>вместо этого попробуйте использовать команду shift:</p><pre><code>:loop if [%1] neq [] ( type %1 ) else ( goto end ) shift goto loop :end </code></pre><p>shift переместит все параметры на один, поэтому% 2 становится% 1, а% 3 становится% 2 и т.д.</p>

<p>я использую их как быстрые ссылки на часто используемые каталоги. пример файла с именем "sandbox.bat", который находится в каталоге в моем path</p><pre><code>explorer "c:\documents and settings\myusername\desktop\sandbox" </code></pre><p>вызов сценария просто win + r -> песочница</p>

<p>очень старый (около 1990 г.) прием для получения общего размера переменных среды:</p><pre><code>set > test dir test del test </code></pre>

<p>вот один трюк, который я использую для последовательного запуска сценария my nant build без необходимости многократно щелкать командный файл.</p><pre><code>:codeline nant.exe -buildfile:alltargets.build -l:build.log build.product @pause goto :codeline </code></pre><p>что произойдет, так это то, что после того, как ваше решение завершит сборку, оно будет приостановлено. и затем, если вы нажмете любую клавишу, он снова запустит скрипт сборки. очень удобно, должен сказать.</p>

<p>также есть команда edlin. хотя это может быть старый инструмент-ублюдок, когда-то использовавшийся для линейного редактирования текста, тот факт, что его можно контролировать из командной строки, делает его довольно полезным для пакетного скриптинга, главным образом потому, что, как и в любом другом случае, когда вы используете edlin, он единственный доступный инструмент. в конце концов, edlin - это не тот инструмент, который вы обычно хотели бы использовать для редактирования текста, если только вы не мазохист. цитирую тима паттерсона (человека, который это написал): "я был в ужасе, когда узнал, что ibm использует его, а не выбрасывает в окно".</p><p>примечание. edlin добавляет устаревшие маркеры eof (1a) в редактируемые файлы. если вам нужно удалить их, вам, вероятно, придется использовать debug.</p>