¿Cómo puedo ejecutar un programa externo desde C y analizar su salida?

7 minutos de lectura

avatar de usuario
jose matthews

Tengo una utilidad que genera una lista de archivos requeridos por un juego. ¿Cómo puedo ejecutar esa utilidad dentro de un programa C y tomar su salida para poder actuar sobre ella dentro del mismo programa?

ACTUALIZACIÓN: Buena decisión sobre la falta de información. La utilidad escupe una serie de cadenas, y se supone que esto es portátil en Mac/Windows/Linux. Tenga en cuenta que estoy buscando una forma programática de ejecutar la utilidad y conservar su salida (que va a stdout).

  • ver también stackoverflow.com/questions/125828/…

    – rogerdpack

    25/09/2012 a las 22:30

  • Si también desea stderr, puede redirigir, por ejemplo, llamar a ls nonexistant-name 2>&1

    – Vic

    10 de abril de 2013 a las 3:11

  • Esto no es un duplicado; la pregunta vinculada es específico de C++mientras que esta pregunta es sobre C.

    – Kyle Strand

    22 de marzo de 2016 a las 22:21

  • Voy a votar para reabrir esta pregunta ya que no es un duplicado, se trata de C, no de C++

    – hassan

    20 de junio de 2017 a las 9:51

  • ver también stackoverflow.com/questions/9405985/…

    – Munición Goettsch

    3 sep 2017 a las 15:37

avatar de usuario
MestreLeón

Como otros han señalado, popen() es la forma más estándar. Y dado que ninguna respuesta proporcionó un ejemplo usando este método, aquí va:

#include <stdio.h>

#define BUFSIZE 128

int parse_output(void) {
    char *cmd = "ls -l";    
    
    char buf[BUFSIZE];
    FILE *fp;

    if ((fp = popen(cmd, "r")) == NULL) {
        printf("Error opening pipe!\n");
        return -1;
    }

    while (fgets(buf, BUFSIZE, fp) != NULL) {
        // Do whatever you want here...
        printf("OUTPUT: %s", buf);
    }

    if (pclose(fp)) {
        printf("Command not found or exited with error status\n");
        return -1;
    }

    return 0;
}

Salida de muestra:

OUTPUT: total 16
OUTPUT: -rwxr-xr-x 1 14077 14077 8832 Oct 19 04:32 a.out
OUTPUT: -rw-r--r-- 1 14077 14077 1549 Oct 19 04:32 main.c

  • No debería if(pclose(fp)) ser if(pclose(fp) == -1)?

    – Spikatrix

    31 de marzo de 2016 a las 9:03

  • @CoolGuy: depende de lo que quieras. pclose() devolver -1 si hubo un error al obtener el estado de salida del comando; de lo contrario, devuelve el estado de salida en sí. Como los comandos establecen tradicionalmente el estado de salida 0 para indicar el éxito, marcando if(pclose(fp)) estamos probando errores en cualquiera pclose() o el comando.

    – Mestre León

    31 de marzo de 2016 a las 22:48

  • Muchas gracias por este ejemplo, canaliza la salida de otro programa a la salida del programa actual. ¡Gracias!

    – José

    30 de marzo de 2019 a las 0:20

  • Otro ejemplo: ¿Hay alguna manera de obtener la salida de un comando de Linux (como ifconfig) en un archivo .txt usando un programa C?

    – Gabriel grapas

    9 dic 2021 a las 6:31


  • @GabrielStaples: fgets() es más adecuado cuando se lee salida de texto en lugar de binaria, ya que obtiene automáticamente una línea a la vez, dividiéndola en saltos de línea. Ambos requieren la while bucle, ya que no puede estar seguro de que toda la salida quepa en BUFSIZE.

    – Mestre León

    9 dic 2021 a las 19:51


avatar de usuario
dmckee — gatito ex-moderador

Para problemas simples en entornos Unix-ish intente popen().

De la página del manual:

La función popen() abre un proceso al crear una tubería, bifurcar e invocar el shell.

Si usa el modo de lectura, esto es exactamente lo que solicitó. No sé si está implementado en Windows.

Para problemas más complicados, desea buscar la comunicación entre procesos.

  • algunos ejemplos de cómo usar correctamente popen() sería bueno.

    – Alexej Magura

    29 de julio de 2013 a las 19:29

  • He agregado un enlace a la página de manual de Open Group para la función, que incluye un ejemplo. Básicamente popen te da un puntero de archivo muy parecido fopen. Es solo que le permite escribir en la entrada estándar o leer desde la salida estándar de un programa en lugar de interactuar con un archivo de disco. eso es de unix “todo es un archivo” filosofía en el trabajo. Algunas implementaciones amplían el estándar al permitir la comunicación bidireccional.

    – dmckee — gatito ex-moderador

    30 de julio de 2013 a las 1:09

  • Esta respuesta indica que popen está disponible en Windows.

    – Jonathan Reinhart

    25 de junio de 2015 a las 19:17

  • Para conocer la solución que utiliza los identificadores de archivos sin formato (si necesita E/S asíncrona, por ejemplo), consulte stackoverflow.com/questions/9405985/…

    – Munición Goettsch

    3 sep 2017 a las 15:36

avatar de usuario
Adán Pierce

popen es compatible con Windows, consulte aquí:

http://msdn.microsoft.com/en-us/library/96ayss4b.aspx

Si quieres que sea multiplataforma, popen es el camino a seguir.

avatar de usuario
David J. Sokol

Bueno, suponiendo que está en una línea de comando en un entorno de Windows, puede usar canalizaciones o redireccionamientos de línea de comando. Por ejemplo,

commandThatOutputs.exe > someFileToStoreResults.txt

o

commandThatOutputs.exe | yourProgramToProcessInput.exe

Dentro de su programa, puede usar las funciones de entrada estándar de C para leer la salida de otros programas (scanf, etc.): http://irc.essex.ac.uk/www.iota-six.co.uk/c/c1_standard_input_and_output.asp . También puede usar el archivo de ejemplo y usar fscanf. Esto también debería funcionar en Unix/Linux.

Esta es una pregunta muy genérica, es posible que desee incluir más detalles, como qué tipo de salida es (¿solo texto o un archivo binario?) y cómo desea procesarlo.

Editar: ¡Hurra aclaración!

Redirigir STDOUT parece ser problemático, tuve que hacerlo en .NET y me dio todo tipo de dolores de cabeza. Parece que la forma correcta de C es generar un proceso secundario, obtener un puntero de archivo y, de repente, me duele la cabeza.

Así que aquí hay un truco que usa archivos temporales. Es simple, pero debería funcionar. Esto funcionará bien si la velocidad no es un problema (golpear el disco es lento) o si es desechable. Si está creando un programa empresarial, probablemente lo mejor sea buscar en la redirección STDOUT, utilizando lo que otras personas recomendaron.

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
    FILE * fptr;                    // file holder
    char c;                         // char buffer


    system("dir >> temp.txt");      // call dir and put it's contents in a temp using redirects.
    fptr = fopen("temp.txt", "r");  // open said file for reading.
                                    // oh, and check for fptr being NULL.
    while(1){
        c = fgetc(fptr);
        if(c!= EOF)
            printf("%c", c);        // do what you need to.
        else
            break;                  // exit when you hit the end of the file.
    }
    fclose(fptr);                   // don't call this is fptr is NULL.  
    remove("temp.txt");             // clean up

    getchar();                      // stop so I can see if it worked.
}

Asegúrese de verificar los permisos de su archivo: en este momento, esto simplemente arrojará el archivo en el mismo directorio que un exe. Es posible que desee considerar el uso /tmp en nix, o C:\Users\username\Local Settings\Temp en Vista, o C:\Documents and Settings\username\Local Settings\Temp in 2K/XP. Pienso que el /tmp funcionará en OSX, pero nunca he usado uno.

En Linux y OS X, popen() realmente es su mejor apuesta, como señaló dmckee, ya que ambos sistemas operativos admiten esa llamada. En Windows, esto debería ayudar: http://msdn.microsoft.com/en-us/library/ms682499.aspx

avatar de usuario
Angus Connell

La documentación de MSDN dice que si se usa en un programa de Windows, la función _popen devuelve un puntero de archivo no válido que hace que el programa deje de responder indefinidamente. _popen funciona correctamente en una aplicación de consola. Para crear una aplicación de Windows que redirija la entrada y la salida, consulte Creación de un proceso secundario con entrada y salida redirigidas en el SDK de Windows.

avatar de usuario
JB.

Puedes usar system() como en:

system("ls song > song.txt");

donde ls es el nombre del comando para enumerar el contenido de la canción de la carpeta y song es una carpeta en el directorio actual. Archivo resultante song.txt se creará en el directorio actual.

  • ¿Qué pasa si quiero redirigir la salida de otros programas a un archivo? no es un comando os

    – Amina Da.

    17 de abril de 2016 a las 1:30

  • No, esta es una muy mala manera de hacerlo. Hágalo correctamente usando canalizaciones, no deje archivos temporales en todo el sistema de archivos.

    – Búho

    5 oct 2018 a las 14:55

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad