Quelle est la raison de “…” n’est pas reconnu comme une commande interne ou externe, un programme exploitable ou un fichier de commandes?

J’ai un extrait d’une ligne qui fonctionne parfaitement dans la ligne de commande, mais qui échoue et génère des erreurs lorsque je l’exécute dans le cadre d’un script de traitement par lots.

Les commandes ci-dessous se comportent comme prévu, supprimant tous les sous-dossiers vides du dossier.

for /f "delims=" %d in ('dir /s /b /ad ^| sort /r') do rd "%d"

Cependant, lorsqu’il est placé dans un fichier de commandes comme ça …

FOR /f "delims=" %%d in ('dir /s /b /ad ^| sort /r') do rd "%%d"

… il génère l’erreur standard: le Sort is not recognised as an internal or external command...

J’expérimente depuis une heure ou deux avec et sans échapper à la pipe, en changeant l’ordre des options, en recherchant la documentation à la fois de dir et de sort , etc., mais je n’ai toujours pas compris passe ici. Le rest du fichier batch, qui ne contient que quelques lignes, fonctionne correctement, et c’est la seule ligne qui échoue.

Quelqu’un peut-il aider? Merci d’avance, je l’apprécierais vraiment.

A) Comment l’interpréteur de commandes Windows recherche-t-il les commandes?

L’interpréteur de commandes Windows recherche une commande à exécuter qui

  1. n’est pas une commande interne de cmd.exe et
  2. est juste spécifié avec le nom de fichier sans extension de fichier et sans chemin

pour un fichier correspondant à la command.* pattern command.* et ayant une extension de fichier répertoriée dans la variable d’environnement locale PATHEXT

  1. d’abord dans le répertoire courant et
  2. next dans tous les répertoires de la variable d’environnement locale PATH .

SORT et FIND et FINDSTR et ROBOCOPY et XCOPY et beaucoup d’autres commandes ne sont pas des commandes internes de cmd.exe . Ce sont des applications de console installées avec Windows situé dans le répertoire %SystemRoot%\System32 portant le nom de fichier sort.exe , find.exe , findstr.exe , robocopy.exe , xcopy.exe , …

Ces applications de console disponibles par défaut sous Windows sont appelées commandes externes pour mieux les distinguer des applications de console non installées avec le système d’exploitation Windows.


B) Comment la variable d’environnement PATH est-elle définie?

Il existe 3 types de variables PATH :

  1. Système PATH utilisé pour tous les comptes et stocké dans le registre Windows sous la clé:

     HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment 
  2. User PATH utilisé uniquement pour le compte courant et stocké dans le registre Windows sous la clé:

     HKEY_CURRENT_USER\Environment 
  3. Local PATH qui est toujours une copie du PATH local du processus parent qui a démarré le processus en cours.

Windows concatène le système et l’ utilisateur PATH à PATH local pour l’instance de l’Explorateur Windows utilisée comme bureau Windows avec les raccourcis sur l’écran du bureau et le menu Démarrer de Windows en tant qu’interface visible pour l’utilisateur.

Au démarrage d’un nouveau processus, l’intégralité de la table de variables d’environnement actuellement active du processus en cours est copiée pour le nouveau processus par Windows.

Le processus parent ne peut pas modifier les variables d’environnement d’un processus enfant, et un processus enfant ne peut pas modifier les variables d’environnement de son processus parent.

Cela signifie qu’une fois qu’un processus comme cmd.exe été démarré pour l’exécution d’un fichier de commandes, le processus possède son propre ensemble de variables d’environnement que seul le processus lui-même peut modifier. Aucun autre processus ne peut modifier les variables d’environnement d’un processus en cours d’exécution.


C) Que signifie le message d’erreur?

Le message d’erreur

“…” n’est pas reconnu comme commande interne ou externe,
programme exploitable ou fichier de commandes.

signifie toujours que

  1. le nom de fichier d’un

    • application de la console
    • Application graphique
    • script (fichier batch, script PowerShell, script Perl, VBScript, JScript, …)

    a été spécifié pour l’exécution probablement sans extension de fichier et sans chemin (complet) vers le fichier exécutable / script et

  2. Windows n’a pas réussi à trouver un fichier correspondant au modèle FileName.* Avec une extension de fichier répertoriée dans la variable d’environnement PATHEXT dans le répertoire en cours ou dans tout autre répertoire de la variable d’environnement PATH actuellement active.


D) Quelles sont les raisons possibles de ce message d’erreur?

Les raisons typiques sont:

1. Le nom du fichier à exécuter était incorrect en raison d’une erreur de frappe.

Vérifiez caractère par caractère le nom de la commande / exécutable.

2. Le répertoire en cours est différent du répertoire contenant le fichier à exécuter.

Run echo Current directory is: %CD% sur la ligne de commande ou ajoutez cette ligne au fichier de commandes au-dessus de la ligne de commande, ce qui ne permet pas de voir quel est le répertoire actuel.

3. L’exécutable ou le script à exécuter n’est pas du tout installé.

Vérifiez l’existence de l’exécutable à exécuter. Certains packages d’installation ne fonctionnent que si d’autres packages, tels que Java, NPM, PHP, etc., ont été installés auparavant.

4. Le répertoire du fichier à exécuter n’est pas du tout dans PATH .

Ouvrez dans le Panneau de configuration Windows la fenêtre Paramètres du système , cliquez sur Paramètres système avancés sur le côté gauche, cliquez sur le bouton Variables d’environnement et recherchez dans les deux listes le Path d’ Path et leurs valeurs. Par défaut, le Path n’existe que dans la liste des variables système .

5. Un processus / une application en cours d’exécution n’a pas été redémarré après modification du système ou de l’utilisateur PATH .

Une modification du système PATH ou de l’ utilisateur PATH avec la commande setx ou via le Panneau de configuration – Système – Paramètres système avancés a été effectuée par l’utilisateur ou un installateur, mais un processus / une application en cours d’exécution et ouvert / redémarré après modification de PATH . Ceci est nécessaire comme décrit en détail au chapitre F) ci-dessous.

6. La variable LOCAL PATH été modifiée avant sur la ligne de commande ou dans le fichier de commandes.

Exécutez set path sur la ligne de commande ou ajoutez cette commande au fichier de commandes situé au-dessus de la ligne de commande, ce qui ne permet pas de voir les valeurs actuelles des variables d’environnement PATH et PATHEXT .

La dernière raison est responsable du fait que la commande externe SORT n’est pas trouvée lors de l’exécution du fichier de commandes qui contient quelque part au-dessus du set path=...


E) Comment éviter ce message d’erreur?

Best est de coder un fichier batch pour être indépendant sur PATH et PATHEXT et l’ordre des répertoires dans PATH ce qui signifie ici en utilisant la ligne de commande:

 FOR /f "delims=" %%d in ('dir /s /b /ad ^| %SystemRoot%\System32\sort.exe /r') do rd "%%d" 

Toute commande externe dont l’exécutable est stocké dans %SystemRoot%\System32 doit être spécifiée dans un fichier de commandes avec ce chemin et avec l’extension de fichier .exe . Ensuite, l’interpréteur de commandes Windows n’a pas besoin de rechercher un fichier en utilisant PATH et PATHEXT et le fichier batch fonctionne toujours (tant que la variable d’environnement SystemRoot n’est pas également modifiée dans le fichier batch que je n’ai jamais vu).


F) Quand un changement de système ou d’utilisateur PATH est-il appliqué aux processus?

Lorsqu’un utilisateur ouvre une fenêtre d’invite de commande via le menu Démarrer de Windows ou depuis une fenêtre de l’Explorateur Windows, il lance cmd.exe avec l’option /K implicite pour maintenir la fenêtre de la console ouverte après avoir terminé une commande appropriée pour le débogage d’un fichier de commandes. .

Lorsqu’un fichier de commandes est doublé et cliqué dans l’Explorateur Windows, l’utilisateur lance cmd.exe pour traiter le fichier de commandes avec l’option /C implicite pour fermer la fenêtre de la console une fois le traitement par lots terminé. être vu dans ce cas.

Dans les deux cas, Windows crée une copie des variables d’environnement de l’application commençant par cmd.exe généralement Windows Explorer. Par conséquent, le processus de commande démarré a un PATH local dont la valeur est la même que celle du processus parent au démarrage de cmd.exe .

Exemple:

  1. Ouvrez une fenêtre d’invite de commandes, exécutez le title Process1 et exécutez set path .
    La sortie est PATH et PATHEXT comme défini actuellement pour le compte utilisateur actuel dans la fenêtre de la console ayant maintenant le titre de la fenêtre Process1 .

  2. Exécutez set PATH=%SystemRoot%\System32 et ensuite set path nouveau le set path .
    La sortie est à nouveau PATH et PATHEXT , mais avec PATH contenant un seul répertoire maintenant.

  3. Exécutez start "Process2" et exécutez la nouvelle fenêtre de la console avec le titre de la fenêtre Process2 le set path commandes.
    La sortie est PATH et PATHEXT avec les mêmes valeurs que dans Process1 .
    Cela montre que lors du démarrage d’un nouveau processus, les variables d’environnement actuelles du processus en cours d’exécution sont copiées et non pas ce que Windows lui-même stocke actuellement dans le registre Windows.

  4. Exécutez dans Process2 le set PATH= commandes set PATH= et le set path .
    La sortie est uniquement PATHEXT car PATH local n’existe plus pour Process2 .
    Cela démontre que chaque processus peut modifier ses variables d’environnement, y compris la suppression complète.

  5. Passez à la fenêtre Process1 , exécutez le set PATH=%PATH%;%SystemRoot% commandes set PATH=%PATH%;%SystemRoot% et le set path .
    La sortie est PATH avec deux répertoires et PATHEXT .

  6. Exécutez la commande start "Process3" et dans la fenêtre ouverte avec title Process3 le set path commandes.
    La sortie est PATH avec deux répertoires définis également pour Process1 et PATHEXT .

  7. Exécutez dans Process3 le set PATH=%SystemRoot%\System32 commandes set PATH=%SystemRoot%\System32 .

Trois processus de commande s’exécutent avec les valeurs suivantes pour PATH local lorsque %SystemRoot% développe en C:\Windows :

Process1 : PATH=C:\Windows\System32;C:\Windows
Process2 : PATH n’existe pas du tout.
Process3 : PATH=C:\Windows\System32

Alors, que se passe-t-il maintenant en ouvrant Panneau de configuration – Système – Paramètres système avancés – Variables d’environnement et en ajoutant à la liste des variables utilisateur la nouvelle variable d’environnement PATH avec la valeur C:\Temp ou en cas de déjà une variable d’environnement PATH PATH et append ;C:\Temp à la valeur?

Eh bien, tant que la fenêtre de dialog avec le titre Variables d’environnement montrant les deux listes est ouverte, rien ne se passe lors de la modification des variables, jusqu’à ce que l’on clique sur le bouton OK pour reprendre toutes les modifications dans le registre Windows et fermer la fenêtre.

Revenons aux trois processus de commande en cours d’exécution et exécutons dans Process1 , Process2 et Process3 le set path commandes. On peut le voir:

Process1 : PATH=C:\Windows\System32;C:\Windows
Process2 : PATH n’existe pas du tout.
Process3 : PATH=C:\Windows\System32

Rien n’a changé sur les processus en cours d’exécution.

Aucun processus ne peut modifier les variables d’environnement d’un processus en cours d’exécution.

Ouvrez depuis le menu de démarrage de Windows une fenêtre d’invite de commande supplémentaire et exécutez en quasortingème commande le set path commandes. On peut voir que PATH local du quasortingème processus de commande a ajouté le répertoire C:\Temp maintenant.

Fermez ensuite tous les 4 processus de commande et supprimez l’ utilisateur PATH ajouté puis supprimez ;C:\Temp de l’ utilisateur PATH si vous PATH ajouté ce chemin de répertoire auparavant.

Comment est-ce possible si aucun processus ne peut modifier les variables d’environnement d’un processus en cours d’exécution?

Comment la liste des variables d’environnement de l’instance de l’Explorateur Windows fonctionnait-elle en tant que bureau Windows modifié à la fermeture de la fenêtre Variables d’environnement avec le bouton OK ?

La réponse sur ces deux questions a été donnée par eryksun dans son commentaire.

Après avoir écrit les modifications sur les variables système et utilisateur dans le registre en cliquant sur le bouton OK de la fenêtre Variables d’environnement , Windows envoie le message WM_SETTINGCHANGE à toutes les fenêtres de niveau supérieur pour informer les applications en cours sur les parameters système modifiés.

C’est à l’application si ce message d’événement est traité et comment. L’explorateur Windows exécuté en tant que bureau Windows lit les variables d’environnement du registre et met à jour sa liste de variables d’environnement en conséquence. D’autres applications comme Total Commander gèrent également ce message et mettent à jour leurs listes de variables d’environnement. Mais cmd.exe ne le fait pas heureusement car cela serait vraiment problématique.

Est-il possible de modifier une variable système ou utilisateur avec notification via WM_SETTINGCHANGE depuis une fenêtre d’invite de commande ou un fichier de commandes?

Il est possible de modifier la valeur de registre d’une variable d’environnement à l’aide de la commande reg add . Mais cela n’entraîne pas l’envoi WM_SETTINGCHANGE message WM_SETTINGCHANGE à toutes les fenêtres de niveau supérieur. De telles modifications effectuées avec reg add ou avec regedit nécessitent un redémarrage de Windows (ou au moins une déconnexion et une connexion de l’utilisateur actuel) à prendre en compte.

Mais il y a aussi la commande setx qui est conçue pour modifier un système ou une variable utilisateur et qui envoie également le message WM_SETTINGCHANGE à toutes les fenêtres de niveau supérieur après la mise à jour du registre en fonction des arguments spécifiés. Exécuter setx /? dans une fenêtre d’invite de commande pour plus de détails. Mais veuillez tenir compte du fait que setx ne modifie pas la variable d’environnement local du processus de commande en cours d’exécution. Cela doit être fait en utilisant le set commandes utilisé en plus de setx .


G) Comment la variable d’environnement PATHEXT est-elle gérée par Windows?

La variable d’environnement PATHEXT avec la liste des extensions de fichiers est gérée par Windows différemment de la variable d’environnement PATH .

Le système PATHEXT et l’ utilisateur PATHEXT sont PAS concaténés au PATHEXT local .

Un utilisateur PATHEXT remplace le système PATHEXT pour tous les processus exécutés dans l’environnement du compte ayant un utilisateur PATHEXT défini.

Il est défini uniquement une variable d’environnement système PATHEXT par défaut.


H) Est-il possible de désactiver la recherche de fichiers dans le répertoire actuel?

Le processeur de commandes Windows recherche par défaut dans le répertoire en cours si le nom de fichier d’un fichier de script ou d’un exécutable est spécifié sur la ligne de commande ou dans un fichier de commandes sans chemin (sans barre oblique inversée \ ). chaîne d’argument.

Mais sur Windows Vista et versions ultérieures de Windows et sur Windows Server 2003 et les versions de serveur Windows ultérieures, il est en effet possible de désactiver la recherche d’un script / exécutable dans le répertoire actuel sans au moins chemin relatif .\ définissant la variable d’environnement valeur écrite par eryksun dans son commentaire ci-dessous et expliquée par Microsoft dans un article MSDN sur la fonction NeedCurrentDirectoryForExePath .

Voir Suppression du répertoire de travail actuel du chemin pour plus de détails sur l’utilisation de cette variable d’environnement.

Très probablement, vous avez déconné avec la variable PATH . Peut-être que vous écrasez-le ailleurs dans votre script. Étant donné que sort est une commande externe, opposée à toutes les autres commandes de la ligne de commande telles for , dir , rd , qui sont des commandes cmd -internal, la variable PATH est nécessaire pour trouver la commande. Si PATH n’est pas défini, les commandes externes sont recherchées uniquement dans le répertoire de travail en cours. Il existe également une variable PATHEXT nécessaire pour définir des extensions de fichier standard pour les exécutables, telles que .com , .exe . Ainsi, lorsque le sort apparaît dans l’invite de commande ou dans un fichier de commandes, le système recherche dans le répertoire de travail en cours et tous les répertoires spécifiés par la variable PATH un fichier avec le sort nom de base et une des extensions spécifiées par PATHEXT . Le sort commande est en fait appelé sort.exe et se trouve généralement dans C:\Windows\System32 .