2009-05-21 7 views
4

La bibliothèque C standard fournit les fonctions system et popen pour exécuter une commande. Mais existe-t-il un moyen portable de détecter si une commande existe?Chemin portable pour savoir si une commande existe (C/C++)

+0

Par "commande", on dirait que vous voulez dire "un autre programme sur la machine de l'utilisateur"? Pouvez-vous confirmer que c'est l'usage que vous voulez dire? – Stobor

Répondre

5

Non, il n'y a pas de fonction C standard pour cela.

La solution Unix seule est de diviser getenv("PATH") sur : (deux points), et essayer de trouver l'exécutable de commande (avec la fonction stat) dans les répertoires.

+0

+1. Sur Windows, c'est un peu différent: casser ";" pas ":", et vous devez vérifier les fichiers se terminant par (au moins) ".exe", ".com" et ".bat". En fait c'est plus compliqué que ça - si je me souviens bien, cmd.exe recherche d'abord les fichiers .com dans TOUS les répertoires, puis pour les fichiers .exe dans TOUS les répertoires, etc. Je ne me rappelle pas les détails malheureusement, mais c'est * différent de l'ordre utilisé par CreateProcess(). –

+1

Sous Windows, il existe beaucoup plus d'extensions exécutables, telles que .pif, .lnk, .vbs, .scr, etc. Il serait préférable de trouver un appel d'API pour les lister toutes au lieu de les coder en dur. – pts

4

Bien que je ne pense pas qu'il existe une façon complètement portable de faire cela (certains systèmes ne supportent même pas les interpréteurs de commandes), system() renvoie 0 s'il n'y a pas eu d'erreur lors de l'exécution de votre commande. Je suppose que vous pourriez juste essayer d'exécuter votre commande et ensuite vérifier la valeur de retour du système.

Pour vérifier si un interpréteur de commande est disponible, appelez le system(NULL) et recherchez une valeur différente de zéro.

3

est ici un moyen de balayer tous les chemins stockés dans la variable PATH, balayage pour l'mathsat exécutable:

#include <stdlib.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <unistd.h> 

#include <string> 
#include <iostream> 

using namespace std; 

int main() 
{ 
    struct stat sb; 
    string delimiter = ":"; 
    string path = string(getenv("PATH")); 
    size_t start_pos = 0, end_pos = 0; 

    while ((end_pos = path.find(':', start_pos)) != string::npos) 
    { 
     string current_path = 
     path.substr(start_pos, end_pos - start_pos) + "/mathsat"; 

     if ((stat(mathsat_path.c_str(), &sb) == 0) && (sb.st_mode & S_IXOTH)) 
     { 
      cout << "Okay" << endl; 
      return EXIT_SUCCESS; 
     } 

     start_pos = end_pos + 1; 
    } 

    return EXIT_SUCCESS; 
} 
6

Pour les systèmes POSIX je trouve que cela fonctionne très bien (je vérifie pour avconv dans cet exemple):

if (system("which avconv > /dev/null 2>&1")) { 
    // Command doesn't exist... 
} else { 
    // Command does exist, do something with it... 
} 

Redirect/dev/null est simplement d'éviter quoi que ce soit en cours d'impression à stdout. Il repose sur la valeur de sortie de la commande quelle seule.

Questions connexes