Supprimer la sortie de ligne de commande

118

J'ai un simple fichier batch comme celui-ci:

Écho off

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

pause

Si "test.exe" n'est pas en cours d'exécution, j'obtiens ce message:

ERREUR: le processus "test.exe" est introuvable.

Pourquoi ce message d'erreur s'affiche-t-il, même si j'ai redirigé la sortie vers NUL?

Comment puis-je supprimer cette sortie?

JosephStyons
la source

Réponses:

212

Parce que les messages d'erreur vont souvent stderrpas stdout.

Changez l'invocation en ceci:

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

et tout ira mieux.

Cela fonctionne parce que stdoutle descripteur de fichier 1 et stderrle descripteur de fichier 2 par convention. (0 est stdin, d'ailleurs.) La 2>&1copie du descripteur de fichier de sortie 2 à partir de la nouvelle valeur de 1, qui vient d'être redirigée vers le périphérique nul.

Cette syntaxe est (vaguement) empruntée à de nombreux shells Unix, mais vous devez être prudent car il existe des différences subtiles entre la syntaxe du shell et CMD.EXE.

Mise à jour: Je sais que l'OP comprend la nature particulière du "fichier" nommé NULdans lequel j'écris ici, mais un commentateur ne l'a pas fait et permettez-moi donc de m'éloigner un peu plus de cet aspect.

En remontant jusqu'aux premières versions de MSDOS, certains noms de fichiers ont été préemptés par le noyau du système de fichiers et utilisés pour désigner des périphériques. La première liste de ces noms inclus NUL, PRN, CON, AUXet à COM1travers COM4. NULest le périphérique nul. Il peut toujours être ouvert en lecture ou en écriture, n'importe quel montant peut y être écrit et les lectures réussissent toujours mais ne renvoient aucune donnée. Les autres incluent le port d'imprimante parallèle, la console et jusqu'à quatre ports série. À partir de MSDOS 5, il y avait plusieurs autres noms réservés, mais la convention de base était très bien établie.

Lorsque Windows a été créé, il a commencé sa vie comme une couche de commutation d'application assez mince au-dessus du noyau MSDOS, et avait donc les mêmes restrictions de nom de fichier. Lorsque Windows NT a été créé comme un véritable système d'exploitation à part entière, les noms comme NULet COM1étaient trop largement supposés fonctionner pour permettre leur élimination. Cependant, l'idée que les nouveaux appareils obtiendraient toujours des noms qui bloqueraient les futurs utilisateurs de ces noms pour les fichiers réels est évidemment déraisonnable.

Windows NT et toutes les versions qui suivent (2K, XP, 7 et maintenant 8) utilisent tous l' espace de noms NT beaucoup plus élaboré à partir du code du noyau et du code d'espace utilisateur soigneusement construit et hautement non portable. Dans cet espace de nom, les pilotes de périphérique sont visibles dans le \Devicedossier. Pour prendre en charge la compatibilité descendante requise, il existe un mécanisme spécial utilisant le \DosDevicesdossier qui implémente la liste des noms de fichiers réservés dans n'importe quel dossier du système de fichiers. Le code utilisateur peut parcourir cet espace de nom interne en utilisant une couche API sous l'API Win32 habituelle; WinObj du groupe SysInternals de Microsoft est un bon outil pour explorer l'espace de noms du noyau .

Pour une description complète des règles entourant les noms légaux des fichiers (et des périphériques) dans Windows, cette page sur MSDN sera à la fois informative et intimidante. Les règles sont beaucoup plus compliquées qu'elles ne devraient l'être, et il est en fait impossible de répondre à quelques questions simples telles que "combien de temps dure le nom de chemin complet légal le plus long?".

RBerteig
la source
5
Merci pour la réponse et surtout pour l'explication.
JosephStyons
Une recommandation: taskkill /im "test.exe" /f >%temp%\nul 2>&1 & del %temp%\nul. Cela empêchera un fichier vide vide d'être placé dans le répertoire local
Samy Bencherif
11
@SamyBencherif, NULest un nom de fichier réservé et correspond au périphérique NUL. Vous ne pouvez pas créer un fichier réel nommé NULdans aucun répertoire.
RBerteig du
7

Utilisez plutôt ce script:

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

Ce que 2>&1fait réellement la pièce, c'est qu'elle redirige la stderrsortie vers stdout. Je vais mieux l'expliquer ci-dessous:

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

Tuez la tâche "test.exe". Rediriger stderrvers stdout. Ensuite, redirigez stdoutvers nul.

@pause

Afficher le message de pause Press any key to continue . . . jusqu'à ce que quelqu'un appuie sur une touche.

REMARQUE: le @symbole masque l'invite de chaque commande. Vous pouvez ainsi enregistrer jusqu'à 8 octets.

La version la plus courte de votre script pourrait être:
@taskkill/f /im test.exe >nul 2>&1&pause
Le &caractère est utilisé pour la redirection la première fois et pour séparer les commandes la deuxième fois.
Un @caractère n'est pas nécessaire deux fois dans une ligne. Ce code ne fait que 40 octets, alors que celui que vous avez publié est de 49 octets! J'ai en fait économisé 9 octets. Pour un code plus propre, regardez ci-dessus.

EKons
la source
Oui, je sais que la moitié du message est en fait de savoir comment raccourcir votre code.
EKons
3

mysqldump ne fonctionne pas avec: > nul 2> & 1
Utilisez plutôt: 2> nul
Ceci supprime le message stderr: "Attention: l'utilisation d'un mot de passe sur l'interface de ligne de commande peut être non sécurisée"

Margenn
la source
0

Vous pouvez également le faire à la place:

tasklist | find /I "test.exe" > nul && taskkill /f /im test.exe > nul
Salut mec
la source
Nonobstant le fait que le contexte de la question était des scripts batch, j'ai trouvé que dans PowerShell, la syntaxe ci-dessus échouait avec " out-file: FileStream a été invité à ouvrir un périphérique qui n'était pas un fichier. Pour la prise en charge de périphériques tels que 'com1:' ou 'lpt1: ', appelez CreateFile, puis utilisez les constructeurs FileStream qui prennent un handle de système d'exploitation comme IntPtr. "La solution consiste à remplacer > nulpar >$null.
déversoir le