Sopprime l'output della riga di comando


118

Ho un semplice file batch come questo:

eco spento

taskkill / im "test.exe" / f> nul

pausa

Se "test.exe" non è in esecuzione, ricevo questo messaggio:

ERRORE: il processo "test.exe" non è stato trovato.

Perché viene visualizzato questo messaggio di errore, anche se ho reindirizzato l'output a NUL?

Come posso sopprimere quell'output?

Risposte:


212

Perché i messaggi di errore spesso vanno a stderrno stdout.

Cambia l'invocazione in questo:

taskkill /im "test.exe" /f >nul 2>&1

e tutto andrà meglio.

Funziona perché stdoutè il descrittore di file 1 ed stderrè il descrittore di file 2 per convenzione. (0 è stdin, incidentalmente.) 2>&1Copia il descrittore del file di output 2 dal nuovo valore 1, che è stato appena reindirizzato al dispositivo nullo.

Questa sintassi è (vagamente) presa in prestito da molte shell Unix, ma devi stare attento perché ci sono sottili differenze tra la sintassi della shell e CMD.EXE.

Aggiornamento: so che l'OP comprende la natura speciale del "file" a NULcui sto scrivendo qui, ma un commentatore non l'ha fatto e quindi lasciatemi divagare con un po 'più di dettaglio su questo aspetto.

Tornando alle prime versioni di MSDOS, alcuni nomi di file erano preceduti dal kernel del file system e usati per fare riferimento ai dispositivi. Il primo elenco di quei nomi inclusi NUL, PRN, CON, AUXe COM1attraverso COM4. NULè il dispositivo nullo. Può sempre essere aperto per la lettura o la scrittura, qualsiasi importo può essere scritto su di esso e le letture riescono sempre ma non restituiscono dati. Gli altri includono la porta della stampante parallela, la console e fino a quattro porte seriali. A partire da MSDOS 5, c'erano molti altri nomi riservati, ma la convenzione di base era molto ben stabilita.

Quando è stato creato Windows, ha iniziato la sua vita come uno strato di commutazione dell'applicazione piuttosto sottile sopra il kernel MSDOS, e quindi aveva le stesse restrizioni sul nome del file. Quando Windows NT è stato creato come un vero sistema operativo a sé stante, si presumeva troppo spesso che nomi simili NULe COM1funzionassero per consentirne l'eliminazione. Tuttavia, l'idea che i nuovi dispositivi otterrebbero sempre nomi che bloccherebbero l'utente futuro di quei nomi per i file effettivi è ovviamente irragionevole.

Windows NT e tutte le versioni successive (2K, XP, 7 e ora 8) utilizzano lo spazio dei nomi NT molto più elaborato dal codice del kernel e un codice spazio utente attentamente costruito e altamente non portabile. In quello spazio dei nomi, i driver di dispositivo sono visibili attraverso la \Devicecartella. Per supportare la compatibilità con le versioni precedenti richiesta esiste un meccanismo speciale che utilizza la \DosDevicescartella che implementa l'elenco dei nomi di file riservati in qualsiasi cartella del file system. Il codice utente può esplorare questo spazio dei nomi interno utilizzando un livello API sotto la consueta API Win32; un buon strumento per esplorare lo spazio dei nomi del kernel è WinObj del gruppo SysInternals di Microsoft.

Per una descrizione completa delle regole che circondano i nomi legali dei file (e dei dispositivi) in Windows, questa pagina su MSDN sarà sia informativa che scoraggiante. Le regole sono molto più complicate di quanto dovrebbero essere, ed è effettivamente impossibile rispondere ad alcune semplici domande come "quanto è lungo il nome di percorso pienamente qualificato legale più lungo?".


5
Grazie per la risposta e soprattutto per la spiegazione.
JosephStyons

Una raccomandazione: taskkill /im "test.exe" /f >%temp%\nul 2>&1 & del %temp%\nul. Ciò impedirà che un file vuoto vuoto venga inserito nella directory locale
Samy Bencherif

11
@SamyBencherif, NULè un nome di file riservato e viene mappato al dispositivo NUL. Non è possibile creare un file effettivo denominato NULin qualsiasi directory.
RBerteig,

7

Usa invece questo script:

@taskkill/f /im test.exe >nul 2>&1
@pause

Ciò che la 2>&1parte fa effettivamente è che reindirizza l' stderroutput a stdout. Lo spiegherò meglio di seguito:

@ taskkill / f / im test.exe> ​​nul 2> & 1

Termina l'attività "test.exe". Reindirizza stderra stdout. Quindi, reindirizza stdouta nul.

@pausa

Mostra il messaggio di pausa Press any key to continue . . . finché qualcuno non preme un tasto.

NOTA: il @simbolo nasconde il prompt di ogni comando. Puoi salvare fino a 8 byte in questo modo.

La versione più breve del tuo script potrebbe essere:
@taskkill/f /im test.exe >nul 2>&1&pause
il &carattere viene utilizzato per il reindirizzamento la prima volta e per separare i comandi la seconda volta.
Un @carattere non è necessario due volte di seguito. Questo codice è di soli 40 byte, nonostante quello che hai pubblicato sia di 49 byte! In realtà ho salvato 9 byte. Per un codice più pulito, guarda sopra.


Sì, lo so che metà del post è in realtà come abbreviare il codice.
EKons

3

mysqldump non funziona con: > nul 2> & 1
Usa invece: 2> nul
Questo sopprime il messaggio stderr: "Attenzione: l'utilizzo di una password sull'interfaccia della riga di comando può non essere sicuro"


0

Puoi farlo anche tu invece:

tasklist | find /I "test.exe" > nul && taskkill /f /im test.exe > nul

Nonostante il contesto della domanda fosse script batch, ho scoperto che in PowerShell la sintassi precedente non riesce con " out-file: a FileStream è stato chiesto di aprire un dispositivo che non era un file. Per il supporto di dispositivi come" com1: "o" lpt1: ', chiama CreateFile, quindi utilizza i costruttori FileStream che accettano un handle del sistema operativo come IntPtr. "La soluzione è sostituire > nulcon >$null.
sbarramento
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.