Recursos ocultos dos arquivos em lote do Windows

232

Quais são alguns dos recursos menos conhecidos, mas importantes e úteis, dos arquivos em lotes do Windows?

Diretrizes:

  • Um recurso por resposta
  • Dê uma breve descrição do recurso e um exemplo , não apenas um link para a documentação
  • Limite as respostas à funcionalidade nativa , ou seja, não requer software adicional, como o Windows Resource Kit

Esclarecimento: Nos referimos aqui aos scripts que são processados ​​pelo cmd.exe, que é o padrão nas variantes do WinNT.

(Veja também: Arquivos em lote do Windows: .bat vs .cmd? )

Chris Noe
fonte

Respostas:

185

Continuação da linha:

call C:\WINDOWS\system32\ntbackup.exe ^
    backup ^
    /V:yes ^
    /R:no ^
    /RS:no ^
    /HC:off ^
    /M normal ^
    /L:s ^
    @daily.bks ^
    /F daily.bkf
Chris Noe
fonte
2
Eu estava procurando por isso na semana passada! (não conseguia se lembrar do personagem)
chilltemp
21
O ^ é realmente um caractere de citação. Usando-o, você pode citar <e> para que eles não redirecionem a saída. O ^ no final de uma linha também permite a continuação da linha.
Cheeso
Poderia, por favor, explicar este pequeno scriptlet?
Guerda
2
@furtelwart: Este é o mesmo como se você escreveu tudo em uma única linha: call C:\WINDOWS\system32\ntbackup.exe backup /V:yes /R:no /RS:no /HC:off /M normal /L:s @daily.bks /F daily.bkf. E para entender todos os parâmetros dessa linha, basta executar C:\WINDOWS\system32\ntbackup.exe /?.
Kurt Pfeifle
O debate aprofundado sobre este tópico, em comandos longos dividida em várias linhas
jeb
150
PUSHD path

Leva você ao diretório especificado pelo caminho .

POPD

Leva você de volta ao diretório do qual você "empurrou".

corvo
fonte
5
Isso também funciona como uma pilha completa, para que você possa colocar muitos diretórios na pilha e continuar aparecendo para voltar aonde estava.
Kibbee
Seriamente? Como eu nunca ouvi falar desse recurso antes ?!
Josh Hinman
4
Execute 'cmd.exe' e digite 'help' e digite 'help pushd' ou 'pushd /?'.
22468
86
Se você enviar para um caminho UNC, ele mapeará automaticamente uma unidade para você e o popd a removerá.
Ferruccio
2
+1 especialmente para o recurso UNC, você deve adicioná-lo à sua resposta.
3111 Adam Mitz
109

Não tenho certeza de quão útil isso seria em um arquivo em lotes , mas é um comando muito conveniente para usar no prompt de comando:

C:\some_directory> start .

Isso abrirá o Windows Explorer na pasta "some_directory".

Eu achei isso uma grande economia de tempo.

LeopardSkinPillBoxHat
fonte
1
bem, eu também uso. Eu tenho um arquivo "open.cmd" em um dos diretórios PATH, e a única coisa nesse arquivo é "@start". ;)
Paulius
5
'explorer' também faz o mesmo que 'start' C: \ some_directory> explorer.
Raio
1
Costumo digitar isso como [start "". ] (colchetes para maior clareza) porque start às vezes é exigente quanto o primeiro parâmetro é um título.
system PAUSE
1
Se você estiver em um Mac, open .faça o mesmo.
Grant Paul
1
startfaz muito mais do que apenas abrir a pasta atual. Você pode transmitir qualquer arquivo e ele será aberto com o visualizador configurado. Dê-lhe um URL e seu navegador padrão é aberto, etc ...
idbrii
87

Sempre achei difícil ler comentários marcados por uma palavra-chave em cada linha:

REM blah blah blah

Mais fácil de ler:

:: blah blah blah
Chris Noe
fonte
8
Ouvi :: é mais eficiente que o REM porque o REM tenta fazer a expansão da variável de ambiente nas coisas que ocorrem depois dela, mas :: não.
22868 Scott Langham
47
De fato, :: é apenas um rótulo com um nome engraçado; portanto, :: não funcionará se você o usar dentro de um bloco (entre parênteses), pois os rótulos também não são permitidos. REM trabalha lá, é claro.
mihi
Observe que essa remé uma palavra-chave documentada, enquanto ::é apenas um detalhe de implementação. Embora seja improvável que ::isso pare de funcionar, geralmente é aconselhável não confiar em comportamentos não documentados.
Joey
Você pode até usar goto :para pular para o rótulo. :-)e goto -)também irá funcionar.
Sven Marnach
79

Substrações variáveis:

> set str=0123456789
> echo %str:~0,5%
01234
> echo %str:~-5,5%
56789
> echo %str:~3,-3%
3456
Chris Noe
fonte
3
Feio, mas muito útil!
Guerda
1
sons @furtelwart como esse poderia ser o lema lote
rzrgenesys187
isso é ótimo para formatação de datas (no entanto, o problema que eu encontrei foi que o Vista / 7 e o xp saem DATE de maneira diferente) #
Daniel Daniel
Observe que, infelizmente, isso não pode ser combinado com as variáveis ​​locais dos loops FOR ( for %a in ...), pois elas não exigem o sinal de porcentagem de fechamento, assim como as variáveis ​​de ambiente; você deve primeiro atribuí-los a uma variável de ambiente (usando expansão atrasada!) e depois extrair uma substring.
RolKau
Isso é inevitável se você quiser fazer algo com datas (por exemplo, nomes de arquivos de backup). Depois de testemunhar a feiúra geral da linha de comando do Windows, vejo por que o Windows é principalmente apontar e clicar :) Embora eles digam que o novo PowerShell é melhor.
Halil Özgür
72

O comando FOR ! Embora eu odeie escrever arquivos em lote, sou grato por isso.

FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k

analisaria cada linha em myfile.txt, ignorando as linhas que começassem com ponto e vírgula, passando o segundo e o terceiro token de cada linha para o corpo for, com tokens delimitados por vírgulas e / ou espaços. Observe as instruções do corpo for referência% i para obter o segundo token,% j para obter o terceiro token e% k para obter todos os tokens restantes após o terceiro.

Você também pode usar isso para percorrer diretórios, conteúdo de diretórios, etc.

TheSoftwareJedi
fonte
4
Eu achei os loops FOR dos arquivos em lotes limitados e terríveis de escrever, mas às vezes são úteis.
ya23
2
Desculpe meu confuso, mas como isso é subutilizado? Acho que se você não conhece os loops FOR, não conhece o script em lote.
Codificando com estilo
11
Subutilizado ou não, é tortura. (Alguns argumentam um mal necessário.)
Harpo
Eu tive que usá-lo algumas vezes e a pessoa que criou essa sintaxe deve ser demitida. De um canhão. Dentro do sol. É TÃO ruim.
VitalyB
1
@CodingWithStyle: Toda vez que eu preciso escrever um loop for em um arquivo em lotes, o script se torna um iniciador de bash e reescreve o script em bash (ou python):)
idbrii
60

Em vez de agrupar um script com REM ou :: lines, faço o seguinte na parte superior de cada script:

@echo OFF
goto :START

Description of the script.

Usage:
   myscript -parm1|parm2 > result.txt

:START

Observe como você pode usar os caracteres de canal e redirecionamento sem escapar deles.

Patrick Cuff
fonte
3
Seria ainda mais legal se você marcasse% 1 para "/?" e então você pode repetir essa seção como texto de ajuda.
Demoncodemonkey 10/09/09
6
Hmm, programação em lote alfabetizada ?!
Muhammad Alkarouri
54

O caminho (com unidade) em que o script está: ~ dp0

set BAT_HOME=%~dp0
echo %BAT_HOME%
cd %BAT_HOME%
RealHowTo
fonte
Eu normalmente uso% CD% para isso. Talvez não esteja disponível em todas as versões de shell do DOS?
Saul Dolgin
11
% CD% é o diretório atual, enquanto% ~ dp0 é o diretório em que o script em execução está localizado.
RealHowTo
Além disso, não acho que% CD% existia antes ... XP, talvez. Eu sei que algumas versões mais antigas do Windows não a possuem.
Thomas Owens
1
Você deve usar cd / d% BAT_HOME%, se o bastão estiver em outra unidade. Se bem me lembro, isso não funcionará com DOSes mais antigos.
ketorin
cd ou pushd% BATH_HOME% não funcionará se você executar um lote em um caminho de rede.
Benoit
49

A parte% ~ dp0 já foi mencionada, mas na verdade há mais: os caracteres após o ~ definem as informações que são extraídas.
Nenhuma letra resulta no retorno do nome do arquivo de correção
d - retorna a letra da unidade
p - retorna o caminho
s - retorna o caminho curto
x - retorna a extensão do arquivo
Portanto, se você executar o script test.bat abaixo no arquivo c: \ Temp \ nome do diretório longo \ pasta,

@echo off
echo %0
echo %~d0
echo %~p0
echo %~dp0
echo %~x0
echo %~s0
echo %~sp0

você obtém a seguinte saída

test
c:
\Temp\long dir name\
c:\Temp\long dir name\
.bat
c:\Temp\LONGDI~1\test.bat
\Temp\LONGDI~1\

E se um parâmetro for passado para o seu script como em
teste c: \ temp \ mysrc \ test.cpp
as mesmas manipulações podem ser feitas com a variável% 1.

Mas o resultado da expansão de% 0 depende da localização!
No "nível superior" do lote, ele se expande para o nome do arquivo do lote atual.
Em uma função (chamada), ela se expande para o nome da função.

@echo off
echo %0
call :test
goto :eof

:test
echo %0
echo %~0
echo %~n0

A saída é (o batchfile é iniciado com myBatch.bat)

myBatch.bat
:test
:test
myBatch
Hartmut
fonte
43

Usando CALL, EXIT / B, SETLOCAL & ENDLOCAL, você pode implementar sub-rotinas com variáveis ​​locais.

exemplo:

@echo off

set x=xxxxx
call :sub 10
echo %x%
exit /b

:sub
setlocal
set /a x=%1 + 1
echo %x%
endlocal
exit /b

Isso imprimirá

11
xxxxx

mesmo que: sub modifique x.

Ferruccio
fonte
6
Você deve usar goto: eof em vez de exit / b, faz a mesma coisa, mas é a maneira mais padrão de fazê-lo.
Philibert Perusse
2
Existe um padrão para isso? O_o
Paulius
3
Meu erro. Eu pensei que você quisesse definir explicitamente um rótulo: eof e fazer um goto para isso. Não sabia que havia um rótulo implícito: eof no final de cada arquivo em lotes.
Ferruccio
3
No entanto, se você quiser que uma sub-rotina defina um nível de erro, será necessário usar exit / b. Por exemplo: exit / b 3
Chris Noe
6
Eu achei melhor usar "exit / B" em vez de "goto: eof" para retornar de uma sub-rotina, "goto: eof" tem o problema de que você pode retornar um código de erro quando quiser engoli-lo. Por exemplo, se você usar "se existe algum eco de arquivo, está aqui", isso definirá o nível de erro se algum arquivo não existir, mas isso não está errado e não é um código de erro que você deseja retornar (que é o que " goto: eof "faria).
23430 Scott Langham
42

Truque furtivo para esperar N segundos (não faz parte do cmd.exe, mas não é um software extra, pois vem com o Windows), consulte a linha de ping. Você precisa de pings N + 1, pois o primeiro ping sai sem demora.

    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
paxdiablo
fonte
2
Melhor ainda é colocar isso em um arquivo como sleep.bat, para poupar o trabalho de reescrevê-lo repetidamente.
erjiang
1
... e colocar o sleep.bat em algum diretório na variável de ambiente PATH
Scoregraphic
Sou contra colocar isso de fora, torna o menos portátil ... nos sistemas Windows.
sorin
37

Escapando do "encanamento":

echo ^| ^< ^> ^& ^\ ^^
Chris Noe
fonte
3
Aposto que o caractere de escape do DOS não é bem conhecido. Um bom.
2100 Joshua
12
Ah, isso explicaria por que é a linha de operador continuação bem - ele escapa a nova linha, assim como \ em bash ...
Leander
@leander: Sim, mas ele só pode escapar do LF (e não do CR), porque todos os CRs foram removidos antes
jeb
Então, este é por isso que usar git no Windows para diff contra a submissão anterior ( HEAD^) é problemática.
Daniel Trebbien 24/03
31

Ser capaz de executar comandos e processar a saída (como backticks de '$ ()' no bash).

for /f %i in ('dir /on /b *.jpg') do echo --^> %i

Se houver espaços nos nomes de arquivos, use o seguinte:

for /f "tokens=*" %i in ('dir /on /b *.jpg') do echo --^> %i
paxdiablo
fonte
2
Não funciona com nomes de arquivos que possuem espaços em seus nomes ... Isso funciona: para / f "tokens = *"% i in ('dir / on / b * .jpg') do echo - ^>% i
doekman 02/12/08
Boa pegada. Pessoalmente, acho que os espaços nos nomes dos arquivos são coisas horríveis e horríveis das profundezas do nono círculo do inferno. Mas devemos cuidar deles, eu acho.
paxdiablo
Essa é a sintaxe mais louca que eu já vi. Funciona se você criou esse backtick.bat e passou a string?
Idbrii
30

Criando um arquivo vazio:

> copy nul filename.ext
nzpcmad
fonte
6
@ devio: eco. coloca uma linha vazia. para que o arquivo não fique vazio!
Paulius
4
Eu uso type nul > filename.extpara isso.
Benoit
Bom, eu queria saber se havia um toque equivalente por um longo tempo.
jdelator
Eu sempre useiren > blah.txt
Synetech
28

Para ocultar toda a saída de um comando, redirecione para> nul 2> & 1.

Por exemplo, alguns programas de linha de comando exibem a saída mesmo se você redirecionar para> nul. Mas, se você redirecionar a saída como a linha abaixo, toda a saída será suprimida.

PSKILL NOTEPAD >nul 2>&1

EDIT: Consulte Ignorando a saída de um comando para obter uma explicação de como isso funciona.

aforia
fonte
1
Você sabe como isso funciona? Qual o significado do bit 2> & 1?
Scott Langham
12
O> nul redireciona STDOUT para nul. O 2> & 1 redireciona STDERR para onde quer que STDOUT esteja apontando.
Aphoria 02/12/08
Especificamente, acho que o 2> & 1 é um "clone de manipulador de arquivo", configurando STDERR para um clone de STDOUT. Colocá-lo após o> NUL é importante, porque você deseja clonar STDOUT após o redirecionamento, não antes. (Corrija-me se estiver errado aqui.) #
Leander
1
Para aqueles que se perguntam de onde vem o PSKILL, consulte sysinternals.com . Se você estiver em uma edição Pro, deverá ter um comando TSKILL nativo mais ou menos o mesmo.
Codificando com estilo
1
Se você não tem pskill ou tskill, a maioria dos sistemas Windows que eu usei vem com taskkill.
Idbrii 24/03/11
25
PAUSE

Interrompe a execução e exibe o seguinte prompt:

Pressione qualquer tecla para continuar . . .

Útil se você deseja executar um lote clicando duas vezes no Windows Explorer e realmente deseja ver a saída em vez de apenas um flash da janela de comando.

raven
fonte
Eu dificilmente chamaria isso de "subutilizado", já que o identifico no final de cada script que escrevo. Então, novamente, ele não funciona tão bem quando você quer ter o seu IDE executar o script e capturar a saída, como o IDE não tem como pressione enter para você normalmente ...
Nicholas Flynt
15
Um recurso interessante de "pausa" é que, se não houver um terminal por perto para receber uma "qualquer chave" (por exemplo, se o arquivo em lote for executado a partir de um serviço do sistema), ele detectará isso e continuará ...
leander
4
+1 a Charlie Somerville, isso é tão conhecido que o 'go.bat' de todos os programadores de jogos o usou no início dos anos 90.
LiraNuna 9/09/09
6
Em vez de poluir todos os seus arquivos em lotes (e torná-los irritantes para os geeks da CLI), você pode usar Iniciar / Executar / digite 'cmd / k' e o nome do arquivo em lote. OU altere a string padrão HKCR \ batfile \ shell \ open \ command para 'cmd / k "% 1"% *'. OU crie outro arquivo em lote que execute '@cmd / k $ *', coloque-o na área de trabalho e solte seus outros arquivos em lote. Existem muitas alternativas para PAUSE. Por favor, considere-os.
system PAUSE
1
@gnud: você ainda pode tubo para o script: echo.|batch-with-pause.batterá o mesmo efeito que pressionar o 'any-chave' ...
Kurt Pfeifle
25

O equivalente da festança (e outras conchas)

echo -n Hello # or
echo Hello\\c

que gera " Hello" sem uma nova linha à direita. Um cmd hack para fazer isso:

<nul set /p any-variable-name=Hello

set /pé uma maneira de solicitar ao usuário a entrada. Emite a sequência especificada e aguarda (na mesma linha, ou seja, sem CRLF), para o usuário digitar uma resposta.

<nul simplesmente envia uma resposta vazia ao set /p comando, para que o resultado líquido seja a sequência de prompt emitida. (A variável usada permanece inalterada devido à resposta vazia.)

Os problemas são: Não é possível emitir um sinal de igual à esquerda, e no Vista os caracteres em branco em branco são removidos, mas não no XP.

paxdiablo
fonte
18

Procure e substitua ao configurar variáveis ​​de ambiente:

> @set fname=%date:/=%

... remove o "/" de uma data para uso em nomes de arquivo com registro de data e hora.

e substrings também ...

> @set dayofweek=%fname:~0,3%
SqlACID
fonte
17

Aritmética de número inteiro:

> SET /A result=10/3 + 1
4
Chris Noe
fonte
Quanto tempo o SET conseguiu calcular? Windows XP?
chakrit
1
Se você está perguntando qual o tamanho dos valores, acredito que sejam 32 bits. Então, +/- 2 bilhões.
31510 Chris Noe
1
Acho que a pergunta foi: quanto tempo o SET conseguiu calcular? Desde o Windows XP?
Michael Myers
3
Eu acho que o SET do CMD.EXE foi capaz de calcular desde o NT 3.1. Ele apenas levou muito tempo para qualquer um aviso de que CMD.EXE não era exatamente o mesmo que COMMAND.COM ...
RBerteig
16

Separadores de comando:

cls & dir
copy a b && echo Success
copy a b || echo Failure

Na 2ª linha, o comando após && é executado apenas se o primeiro comando for bem-sucedido.

Na terceira linha, o comando após || só é executado se o primeiro comando falhar.

doekman
fonte
15

Saída de uma linha em branco:

echo.
paxdiablo
fonte
15

Você pode encadear instruções if para obter um efeito como um booleano de curto-circuito `e '.

if foo if bar baz
Jack
fonte
1
Isto é realmente apenas um atalho para o assentamento ifs: if foo ( if bar ( baz ) )(imagine novas linhas após os parênteses.)
idbrii
14

Para converter rapidamente um arquivo de texto Unicode (16 bits / char) em um arquivo ASCII DOS (8 bits / char).

C:\> type unicodeencoded.txt > dosencoded.txt

como bônus, se possível, os caracteres são mapeados corretamente.

RealHowTo
fonte
1
Esse é um arquivo ANSI DOS - ASCII é 7 bits / char.
MarkJ
Lol, esse é um anti-padrão, é provável que essa conversão falhe. A única codificação de 8 bits que suporta Unicode é o UTF-8, mas graças a M $ você não pode ter a página de códigos UTF-8 definida no Windows.
sorin
14

se estrutura de bloco:

if "%VS90COMNTOOLS%"=="" (
  echo: Visual Studio 2008 is not installed
  exit /b
)
Ferruccio
fonte
3
Contanto que você saiba que as variáveis ​​serão expandidas de uma só vez (sem expansão tardia) - ou seja, você não pode usar sensivelmente% ERRORLEVEL% lá.
Duncan Inteligente
Você também não pode usar rótulos lá (o que inclui os comentários :: style) porque isso encerrará prematuramente a instrução if.
Codificando com estilo
2
@ Duncan: Você não deve usar a pseudo-variável de %ERRORLEVEL%qualquer maneira; if errorlevel <foo>é para isso que serve. E isso de fato funciona em tais blocos.
Joey
12

Expansão atrasada de variáveis ​​(com substrings lançados para uma boa medida):

    @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
paxdiablo
fonte
12

Não fornece muita funcionalidade, mas você pode usar o comando title para alguns usos, como fornecer status em um script longo na barra de tarefas ou apenas para aprimorar o feedback do usuário.

@title Searching for ...
:: processing search
@title preparing search results
:: data processing
Hartmut
fonte
2
Interessante. Embora a partir de então você aparentemente perca o recurso regular, que é mostrar o comando em execução no momento. Existe alguma maneira de redefinir isso?
31420 Chris Noe
2
O technet.microsoft.com/en-us/library/bb491017.aspx diz que pode ser redefinido com "title" por si só, mas isso parece não funcionar no Windows 7 ...
ℳ.
11

Não tem um editor à mão e precisa criar um arquivo em lotes?

copy con test.bat

Basta digitar os comandos, pressionar Enter para uma nova linha. Pressione Ctrl-Z e Enter para fechar o arquivo.

Hartmut
fonte
4
Heh, isso me leva de volta.
Codificando com estilo
11

exemplo de subtração de seqüência de caracteres datee timeobter o arquivo chamado "AAAA-MM-DD HH: MM: SS.txt"

echo test > "%date:~0,4%-%date:~5,2%-%date:~8,2% %time:~0,2%_%time:~3,2%_%time:~6,2%.txt"

Eu uso colorpara indicar se meu script termina com êxito, falhou ou precisa de alguma entrada alterando a cor do texto e do plano de fundo. Realmente ajuda quando você tem alguma máquina ao alcance da sua vista, mas bem distante

cor XY

onde X e Y são valor hexadecimal de 0para F, onde X - fundo, Y - texto, quando X = Y cor não será alterada.

cor Z

altera a cor do texto para 'Z' e define o plano de fundo preto; a 'cor 0' não funciona

para nomes de cores ligue

cor ?

MoreThanChaos
fonte
editado; os _ foram interpretados como itálico. Bom pedaço de código.
@Duncan inteligente: não é verdade, também trabalha no Reino Unido Inglês (embora tecnicamente ele deve ser "cor", grrr)
demoncodemonkey
10

Controle total sobre a saída com caracteres de espaçamento e escape:

echo.    ^<resourceDir^>/%basedir%/resources^</resourceDir^>
paxdiablo
fonte
1
Como isso funciona? O ponto demarca o início da saída de texto?
31420 Chris Noe
3
"echo. x" produzirá "<espaço> x", "echo x" produzirá apenas "x". Isso permite espaços à esquerda. Além disso, o caractere de escape "^" impedirá que o cmd pense que todos esses caracteres "<" e ">" são redirecionamentos de E / S.
paxdiablo
1
echo (é melhor, porque echo cria uma pesquisa de arquivo para um arquivo chamado "eco" se esse arquivo existir o eco falhar, se não, então echo interno é executado, mas é mais lento do que echo (..
jeb
9

O SoftwareJedi já mencionou o comando for, mas vou mencioná-lo novamente, pois é muito poderoso.

A seguir, a saída atual da data no formato AAAAMMDD, eu uso isso ao gerar diretórios para backups.

for /f "tokens=2-4 delims=/- " %a in ('DATE/T') do echo %c%b%a
remonedo
fonte
2
Certamente DATE / T retorna 29/10/2008 na Europa e 29/10/2008 nos EUA ... portanto, pode ser necessária alguma localização! ;-)
Está certo! Mas você pode abusar do comando date para descobrir qual formato de data é usado.
Remonedo 30/10/08
4
É uso excessivo de FOR, imo. Eu acho que eu usaria apenas% DATE: ~ 10,4 %% DATE: ~ 4,2 %% DATE: ~ 7,2% para isso, em vez de executar um comando date e depois analisá-lo.
Codificando com estilo