Funzionalità nascoste dei file batch di Windows


232

Quali sono alcuni dei meno noti, ma importanti e utili funzionalità dei file batch di Windows?

Linee guida:

  • Una funzione per risposta
  • Fornisci sia una breve descrizione della funzione sia un esempio , non solo un collegamento alla documentazione
  • Limitare le risposte alla funzionalità nativa , ovvero non richiede software aggiuntivo, come il Resource Kit di Windows

Chiarimento: facciamo riferimento qui agli script elaborati da cmd.exe, che è l'impostazione predefinita per le varianti di WinNT.

(Vedi anche: file batch di Windows: .bat vs .cmd? )

Risposte:


185

Continuazione della linea:

call C:\WINDOWS\system32\ntbackup.exe ^
    backup ^
    /V:yes ^
    /R:no ^
    /RS:no ^
    /HC:off ^
    /M normal ^
    /L:s ^
    @daily.bks ^
    /F daily.bkf

2
Stavo cercando questa settimana scorsa! (non ricordo il personaggio)
chilltemp,

21
Il ^ è davvero un carattere di citazione. Usandolo, puoi citare <e> in modo che non reindirizzino l'output. Il ^ alla fine di una linea consente anche la continuazione della linea.
Cheeso,

Potresti spiegare questo piccolo scriptlet, per favore?
guerda,

2
@furtelwart: Questo è lo stesso come se hai scritto tutto in una sola riga: 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 per capire tutti i parametri di quella linea, esegui semplicemente C:\WINDOWS\system32\ntbackup.exe /?.
Kurt Pfeifle,

La discussione approfondita su questo argomento, a lunghi comandi suddivisi su più righe
jeb

150
PUSHD path

Ti porta nella directory specificata dal percorso .

POPD

Ti riporta alla directory da cui "hai spinto".


5
Funziona anche come uno stack completo, quindi puoi spingere molte directory nello stack e quindi continuare a saltar fuori per tornare dove eri.
Kibbee,

Sul serio? Come non ho mai sentito parlare di questa funzione prima d'ora ?!
Josh Hinman,

4
Eseguire 'cmd.exe' quindi digitare 'help', quindi digitare 'help pushd' o 'pushd /?'.
paxdiablo,

86
Se si è passati a un percorso UNC, mapperà automaticamente un'unità per te e il popd lo annullerà.
Ferruccio,

2
+1 soprattutto per la funzionalità UNC, è necessario aggiungerlo alla risposta.
Adam Mitz,

109

Non sono sicuro di quanto utile sarebbe in a file batch , ma è un comando molto comodo da usare nel prompt dei comandi:

C:\some_directory> start .

Questo aprirà Windows Explorer nella cartella "some_directory".

Ho trovato questo un grande risparmio di tempo.


1
bene, lo uso anche io. Ho un file "open.cmd" in una delle directory PATH e l'unica cosa in quel file è "@start". ;)
Paulius

5
'explorer' fa anche la stessa cosa di 'start' C: \ some_directory> explorer.
Ray

1
Tendo a digitare questo come [start "". ] (parentesi per chiarezza) perché start a volte è pignolo sul fatto che il primo parametro sia un titolo.
sistema PAUSA

1
Se ti capita di essere su un Mac, open .fa la stessa cosa.
Concedi a Paul il

1
startfa molto di più che aprire semplicemente la cartella corrente. Puoi passarlo qualsiasi file e lo aprirà con il visualizzatore configurato. Dagli un URL e il tuo browser predefinito si aprirà, ecc ...
idbrii

87

Ho sempre trovato difficile leggere i commenti che sono contrassegnati da una parola chiave su ogni riga:

REM blah blah blah

Più facile da leggere:

:: blah blah blah

8
Ho sentito :: è più efficiente di REM perché REM tenta di eseguire l'espansione della variabile di ambiente sulle cose che si verificano dopo di essa, ma :: no.
Scott Langham,

47
In realtà, :: è solo un'etichetta con un nome divertente; pertanto, :: non funzionerà se lo si utilizza all'interno di un blocco (tra parentesi) poiché le etichette non sono consentite nemmeno lì. REM ci lavora ovviamente.
mihi,

Nota però che remè una parola chiave documentata mentre ::è solo un dettaglio di implementazione. Sebbene sia improbabile che ::smetta di funzionare, è generalmente consigliabile non fare affidamento su comportamenti non documentati.
Joey,

Puoi anche usare goto :per saltare all'etichetta. :-)e goto -)funzionerà anche.
Sven Marnach,

79

Sottostringhe variabili:

> set str=0123456789
> echo %str:~0,5%
01234
> echo %str:~-5,5%
56789
> echo %str:~3,-3%
3456

3
Brutto, ma molto utile!
guerda,

1
@furtelwart sembra che potrebbe essere il motto in batch
rzrgenesys187,

fantastico per le date di formattazione (tuttavia il problema che ho riscontrato è che vista / 7 e xp hanno dato una data diversa)
Daniel

Si noti che sfortunatamente, questo non può essere combinato con le variabili locali di FOR loop ( for %a in ...) poiché non richiedono il segno di percentuale di chiusura come le variabili di ambiente; devi prima assegnarli a una variabile d'ambiente (usando l'espansione ritardata!) e quindi estrarre una sottostringa.
RolKau,

Questo è inevitabilmente brutto se vuoi fare qualcosa con le date (ad esempio i nomi dei file di backup). Dopo aver assistito alla bruttezza generale della riga di comando di Windows, vedo perché Windows è principalmente punta e clicca :) Anche se dicono che il nuovo PowerShell è migliore.
Halil Özgür,

72

Il comando FOR ! Mentre odio scrivere file batch, ne sono grato.

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

analizzerebbe ogni riga in myfile.txt, ignorando le righe che iniziano con un punto e virgola, passando il secondo e il terzo token da ciascuna riga al corpo for, con token delimitati da virgole e / o spazi. Notare il riferimento for body statement% i per ottenere il 2 ° token,% j per ottenere il 3 ° token e% k per ottenere tutti i token rimanenti dopo il 3 °.

Puoi anche usarlo per scorrere su directory, contenuti della directory, ecc ...


4
Ho trovato i cicli FOR dei file batch limitati e terribili da scrivere, ma a volte sono utili.
ya23

2
Scusa il mio sconcerto, ma come mai questo è sottoutilizzato? Penso che se non conosci i loop FOR, non conosci gli script batch.
Coding With Style

11
Sottoutilizzato o no, è una tortura. (Alcuni sosterrebbero un male necessario.)
Harpo,

Ho dovuto usarlo alcune volte e la persona che ha creato questa sintassi dovrebbe essere licenziata. Da un cannone. Nel sole. È così male.
VitalyB,

1
@CodingWithStyle: Ogni volta che devo scrivere un ciclo for in un file batch, lo script diventa un lanciatore bash e riscrive invece lo script in bash (o python)
:)

60

Invece di sporcare uno script con REM o :: righe, faccio quanto segue all'inizio di ogni script:

@echo OFF
goto :START

Description of the script.

Usage:
   myscript -parm1|parm2 > result.txt

:START

Nota come puoi usare i caratteri di pipe e reindirizzamento senza sfuggirli.


3
Sarebbe ancora più interessante se si selezionasse% 1 per "/?" e quindi potresti fare eco a quella sezione come testo di aiuto.
demoncodemonkey,

6
Hmm, programmazione batch alfabetica ?!
Muhammad Alkarouri,

54

Il percorso (con unità) in cui lo script è: ~ dp0

set BAT_HOME=%~dp0
echo %BAT_HOME%
cd %BAT_HOME%

Di solito uso% CD% per questo. Forse non è disponibile in tutte le versioni di shell DOS?
Saul Dolgin,

11
% CD% è la directory corrente mentre% ~ dp0 è la directory in cui si trova lo script in esecuzione.
RealHowTo

Inoltre, non credo che% CD% esistesse prima di ... XP, forse. So che alcune versioni precedenti di Windows non ce l'hanno.
Thomas Owens,

1
Dovresti invece usare cd / d% BAT_HOME%, se il pipistrello si trova su un'altra unità. Se ricordo bene, questo non funzionerà con DOS più vecchi, però.
chetorin,

cd o pushd% BATH_HOME% non funzionerà se si esegue un batch su un percorso di rete.
Benoit,

49

Il pezzo% ~ dp0 è già stato menzionato, ma in realtà c'è di più: i caratteri dopo il ~ definiscono le informazioni che vengono estratte.
Nessuna lettera comporta la restituzione del nome del file patch
d - restituisce la lettera dell'unità
p - restituisce il percorso
s - restituisce il percorso breve
x - restituisce l'estensione del file
Quindi, se si esegue lo script test.bat di seguito dal c: \ Temp \ nome dir lungo \ cartella,

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

ottieni il seguente output

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

E se un parametro viene passato nello script come nel
test c: \ temp \ mysrc \ test.cpp,
le stesse manipolazioni possono essere fatte con la variabile% 1.

Ma il risultato dell'espansione di% 0 dipende dalla posizione!
Al "livello superiore" del batch si espande nel nome file batch corrente.
In una funzione (chiamata), si espande al nome della funzione.

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

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

L'output è (il file batch viene avviato con myBatch.bat)

myBatch.bat
:test
:test
myBatch

43

Usando CALL, EXIT / B, SETLOCAL & ENDLOCAL è possibile implementare subroutine con variabili locali.

esempio:

@echo off

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

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

Questo stamperà

11
xxxxx

anche se: sub modifica x.


6
Dovresti piuttosto usare goto: eof invece di exit / b, fa la stessa cosa ma è il modo più standard per farlo.
Philibert Perusse,

2
C'è uno standard per questo? O_o
Paulius

3
Errore mio. Pensavo intendessi definire in modo esplicito un'etichetta: eof e andare a quello. Non mi ero reso conto che esistesse un'etichetta implicita: eof alla fine di ogni file batch.
Ferruccio,

3
Tuttavia, se si desidera che una subroutine imposti un livello di errore, sarà necessario utilizzare exit / b. Ad esempio: uscita / b 3
Chris Noe,

6
Ho trovato meglio usare "exit / B" invece di "goto: eof" per tornare da una subroutine, "goto: eof" ha il problema che potresti restituire un codice di errore quando vuoi ingoiarlo. Ad esempio, se usi "se esiste un file echo è qui", questo imposterà il livello di errore se un file non esiste, ma non è sbagliato e non è un codice di errore che vorresti restituire (che è cosa " goto: eof "farebbe).
Scott Langham,

42

Trucco subdolo per attendere N secondi (non fa parte di cmd.exe ma non è un software aggiuntivo poiché viene fornito con Windows), vedere la riga ping. Hai bisogno di ping N + 1 poiché il primo ping si spegne senza ritardo.

    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

2
Ancora meglio è metterlo in un file come sleep.bat per salvarti il ​​problema di riscriverlo più volte.
erjiang,

1
... e metti sleep.bat in qualche directory nella variabile d'ambiente PATH
Scoregraphic

Sono contrario a metterlo fuori, rende meno portatile ... tra i sistemi Windows.
sorin,

37

In fuga dall'impianto idraulico:

echo ^| ^< ^> ^& ^\ ^^

3
Scommetto che il personaggio di escape DOS non è ben noto. Buona
Joshua,

12
Ah, questo spiegherebbe perché è anche l'operatore di continuazione della linea - sfugge alla nuova riga, proprio come \ in bash ...
magro,

@leander: Sì, ma può solo sfuggire all'LF (e non al CR), perché tutti i CR vengono rimossi prima
jeb

Quindi questo è il motivo per cui usare git su Windows per diff contro il precedente commit ( HEAD^) è problematico.
Daniel Trebbien,

31

Essere in grado di eseguire comandi ed elaborare l'output (come i backtick di '$ ()' in bash).

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

Se ci sono spazi nei nomi dei file, utilizzare questo:

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

2
Non funziona con nomi di file che hanno spazi nei loro nomi ... Funziona: for / f "tokens = *"% i in ('dir / on / b * .jpg') do echo - ^>% i
doekman,

Buona pesca. Personalmente penso che gli spazi nei nomi dei file siano cose orribili e malvagie dalle profondità del nono cerchio dell'Inferno. Ma dovremmo provvedere a loro, immagino.
paxdiablo,

Questa è la sintassi più folle che abbia mai visto. Funziona se hai creato questo backtick.bat e hai passato la stringa?
idbrii,

30

Creazione di un file vuoto:

> copy nul filename.ext

6
@devio: echo. mette una riga vuota. quindi il file non sarebbe vuoto!
Paulius,

4
Lo uso type nul > filename.extper quello.
Benoit

Bello, mi chiedevo se ci fosse un tocco equivalente per molto tempo.
jdelator

Ho sempre usatoren > blah.txt
Synetech il

28

Per nascondere tutto l'output da un comando reindirizzare a> nul 2> & 1.

Ad esempio, alcuni programmi della riga di comando visualizzano l'output anche se si reindirizza a> nul. Ma, se si reindirizza l'output come la riga seguente, tutto l'output verrà soppresso.

PSKILL NOTEPAD >nul 2>&1

EDIT: vedi Ignorare l'output di un comando per una spiegazione di come funziona.


1
Sai come funziona? Qual è il significato del bit 2> & 1?
Scott Langham,

12
Il> nul reindirizza STDOUT a nul. 2> & 1 reindirizza STDERR verso qualsiasi punto di STDOUT.
aphoria,

In particolare, penso che 2> & 1 sia un "clone di filehandle", impostando STDERR su un clone di STDOUT. Inserirlo dopo il> NUL è importante, perché si desidera clonare STDOUT dopo che è stato reindirizzato, non prima. (Per favore, correggimi se sbaglio qui.)
magro,

1
Per quelli di voi che si chiedono da dove viene PSKILL, dai un'occhiata a sysinternals.com . Se sei su un'edizione Pro, dovresti avere un comando TSKILL nativo più o meno lo stesso.
Coding With Style

1
Se non hai pskill o tskill, arriva la maggior parte dei sistemi Windows che ho usato taskkill.
idbrii,

25
PAUSE

Interrompe l'esecuzione e visualizza il seguente prompt:

Premere un tasto qualsiasi per continuare . . .

Utile se si desidera eseguire un batch facendo doppio clic su di esso in Esplora risorse e si desidera effettivamente visualizzare l'output anziché solo un lampo della finestra di comando.


Difficilmente lo chiamerei "sottoutilizzato" mentre lo taggo fino alla fine di ogni sceneggiatura che scrivo. Inoltre, non funziona così bene quando vuoi che il tuo IDE esegua lo script e catturi l'output, poiché l'IDE non ha modo di premere invio per te di solito ...
Nicholas Flynt,

15
Una caratteristica interessante di "pausa" è che se non ci sono terminali in giro per ricevere un "qualsiasi tasto" (ad es. Se il file batch viene eseguito da un servizio di sistema), lo rileva e continua a funzionare ...
magro,

4
+1 su Charlie Somerville, questo è così noto che ogni 'go.bat' del programmatore di giochi lo usava nei primi anni '90.
LiraNuna,

6
Invece di inquinare tutti i tuoi file batch (e renderli fastidiosi da usare per i geek CLI), puoi usare Start / Esegui / quindi digitare 'cmd / k' e il nome del file batch. O cambiare HKCR \ batfile \ shell \ open \ command stringa predefinita in 'cmd / k "% 1"% *'. OPPURE crea un altro file batch che esegue semplicemente '@cmd / k $ *', mettilo sul desktop e rilascia gli altri file batch su di esso. Ci sono molte alternative a PAUSA. Per favore, considerali.
sistema PAUSA

1
@gnud: puoi ancora eseguire il pipe dello script: echo.|batch-with-pause.batavrà lo stesso effetto della pressione del tasto "any-key" ...
Kurt Pfeifle

25

L'equivalente di bash (e altri gusci)

echo -n Hello # or
echo Hello\\c

che genera " Hello" senza una nuova riga finale. Un hack cmd per fare questo:

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

set /pè un modo per richiedere input all'utente. Emette la stringa specificata e quindi attende, (sulla stessa riga, cioè senza CRLF), che l'utente digiti una risposta.

<nul invia semplicemente una risposta vuota a set /p comando, quindi il risultato netto è la stringa del prompt emessa. (La variabile utilizzata rimane invariata a causa della risposta vuota.)

I problemi sono: non è possibile emettere un segno di uguale iniziale e su Vista i caratteri di spazi bianchi principali vengono rimossi, ma non su XP.


18

Cerca e sostituisci quando imposti le variabili di ambiente:

> @set fname=%date:/=%

... rimuove "/" da una data per l'uso nei nomi di file con data e ora.

e anche sottostringhe ...

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

17

Aritmetica intera:

> SET /A result=10/3 + 1
4

Da quanto tempo SET ha la capacità di calcolare? Windows XP?
Chakrit,

1
Se stai chiedendo quanto possono essere grandi i valori, credo che questo sia a 32 bit. Quindi +/- 2 miliardi.
Chris Noe,

1
Penso che la domanda fosse: quanto tempo SET è stato in grado di calcolare? Da Windows XP?
Michael Myers

3
Credo che il SET di CMD.EXE sia stato in grado di calcolare da NT 3.1 o giù di lì. Ci è voluto molto tempo perché qualcuno notasse che CMD.EXE non era esattamente lo stesso di COMMAND.COM ...
RBerteig

16

Separatori di comandi:

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

Alla seconda riga, il comando dopo && viene eseguito solo se il primo comando ha esito positivo.

Alla terza riga, il comando dopo || viene eseguito solo se il primo comando non è riuscito.



15

Puoi incatenare le istruzioni if ​​per ottenere un effetto come un booleano in corto circuito `e '.

if foo if bar baz

1
Questa è davvero solo una scorciatoia per annidare if: if foo ( if bar ( baz ) )(Immagina nuove righe dopo le parentesi.)
idbrii

14

Per convertire rapidamente un file di testo Unicode (16 bit / carattere) in un file DOS ASCII (8 bit / carattere).

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

come bonus, se possibile, i personaggi sono mappati correttamente.


1
Questo è un file ANSI DOS - ASCII è 7 bit / char.
MarkJ

Lol, questo è un anti-pattern, questa conversione è molto probabile che fallisca. L'unica codifica a 8 bit che supporta Unicode è l'UTF-8 ma grazie a M $ non è possibile impostare la codepage UTF-8 su Windows.
sorin,

14

se struttura a blocchi:

if "%VS90COMNTOOLS%"=="" (
  echo: Visual Studio 2008 is not installed
  exit /b
)

3
Finché sei consapevole che le variabili verranno espanse tutte in una volta (senza espansione ritardata), vale a dire che non puoi usare in modo ragionevole% ERRORLEVEL% lì dentro.
Duncan Smart

Non puoi nemmeno usare le etichette lì (che include quei commenti :: style style) perché finirà prematuramente l'istruzione if.
Coding With Style

2
@Duncan: non dovresti comunque usare la pseudo-variabile %ERRORLEVEL%; questo è quello che if errorlevel <foo>serve. E questo in effetti funziona in tali blocchi.
Joey,

12

Espansione ritardata delle variabili (con sottostringhe inserite per buona misura):

    @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

12

Non fornisce molte funzionalità, ma è possibile utilizzare il comando title per un paio di usi, come fornire lo stato su uno script lungo nella barra delle applicazioni o semplicemente per migliorare il feedback degli utenti.

@title Searching for ...
:: processing search
@title preparing search results
:: data processing

2
Interessante. Anche se in seguito apparentemente perdi la funzionalità normale, che è quella di mostrare il comando attualmente in esecuzione. C'è un modo per resettarlo?
Chris Noe,

2
technet.microsoft.com/en-us/library/bb491017.aspx dice che può essere resettato con "title" da solo, ma questo non sembra funzionare su Windows 7 ...
ℳ.

11

Non hai un editor a portata di mano e devi creare un file batch?

copy con test.bat

Digita semplicemente i comandi, premi Invio per una nuova riga. Premi Ctrl-Z e Invio per chiudere il file.


4
Heh, questo mi riporta indietro.
Coding With Style

11

esempio di sottrazione di stringhe su datee timeper ottenere il file denominato "AAAA-MM-GG 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"

Uso colorper indicare se la mia sceneggiatura è andata a buon fine, fallita o necessita di input modificando il colore del testo e dello sfondo. Aiuta davvero quando hai una macchina a portata di mano ma abbastanza lontana

colore XY

dove X e Y sono esadecimali da 0a F, dove X - sfondo, Y - testo, quando X = Y non cambia colore.

colore Z

cambia il colore del testo in 'Z' e imposta lo sfondo nero, 'colore 0' non funzionerà

per i nomi dei colori chiamare

colore ?


modificato; gli _ sono stati interpretati come corsivo. Bel po 'di codice.

@Duncan Smart: non è vero, funziona anche in inglese nel Regno Unito (anche se tecnicamente dovrebbe essere "color", grrr)
demoncodemonkey,

10

Controllo totale sull'output con spaziatura e caratteri di escape .:

echo.    ^<resourceDir^>/%basedir%/resources^</resourceDir^>

1
Come funziona? Il punto delimita l'inizio dell'output del testo?
Chris Noe,

3
"echo. x" produrrà "<spazio> x", "echo x" produrrà solo "x". Ciò consente spazi iniziali. Inoltre, il carattere di escape "^" impedisce a cmd di pensare che tutti quei caratteri "<" e ">" siano reindirizzamenti I / O.
paxdiablo

1
echo (è meglio, perché echo. crea una ricerca di file per un file chiamato "echo" se questo file esiste l'eco. fallisce, in caso contrario viene eseguita l'eco interna, ma è più lenta dell'eco (
jeb

9

TheSoftwareJedi ha già menzionato il comando for, ma lo menzionerò di nuovo in quanto è molto potente.

Di seguito viene visualizzata la data corrente nel formato AAAAMMGG, lo utilizzo quando si generano directory per i backup.

for /f "tokens=2-4 delims=/- " %a in ('DATE/T') do echo %c%b%a

2
Sicuramente DATE / T restituisce il 29/10/2008 in Europa e il 29/10/2008 negli Stati Uniti ... quindi potrebbe essere necessaria una localizzazione! ;-)

Giusto! Ma puoi abusare del comando date per scoprire quale formato di data viene utilizzato.
remonedo,

4
È un uso eccessivo di FOR, imo. Penso che userei solo% DATA: ~ 10,4%% DATA: ~ 4,2%% DATA: ~ 7,2% per quello invece di eseguire un comando data per poi analizzarlo per.
Coding With Style
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.