2012-06-25 20 views
5

In diesem C ProgrammWie umleiten Sie die Ausgabe von System() in eine Datei?

#include <stdio.h> 
#include <fcntl.h> 
int main() 
{ 
    int file = open("Result", O_CREAT|O_WRONLY, S_IRWXU); 

    dup2(stdout, file); 
    system("ls -l"); 

    return 0; 
} 

Ich versuche, die Ausgabe von system() in eine Datei zu umleiten, für die ich habe dup2 verwendet, aber es funktioniert nicht.

Was ist los mit diesem Code?
und, bitte sagen Sie mir, wenn es gibt einen besseren Weg, dies zu tun? (ohne > am Terminal)

+3

Warum verwenden Sie nicht nur die '>' Umleitung im 'system' Befehl? –

+0

Verwenden Sie 'system (" ls -l> Result ");' oder machen Sie Ihre eigene 'fork()'/'exec *()' Kombination. –

+1

Verwenden Sie nicht 'System'. Es ist immer falsch. Führen Sie den Child-Prozess selbst ohne Shell aus, entweder mit 'fork' und' execvp' oder 'posix_spawn'. –

Antwort

4

stdout ist ein FILE * Zeiger des Standard-Ausgabestroms. dup2 erwartet Datei-Deskriptor, auch Sie haben die Parameter Reihenfolge durcheinander gebracht. Verwendung

dup2(file, 1); 

statt.

Auf der besser-zu-tun-dieser Teil. Dieser Weg ist schlecht, weil Sie wahrscheinlich Ihre Standardausgabe wiederherstellen möchten, nachdem dieser Aufruf system abgeschlossen ist. Sie können dies auf verschiedene Arten tun. Sie können dup es irgendwo und dann dup2 es zurück (und schließen Sie die dup ped one). Ich persönlich mag es nicht, eigene cat Implementierungen wie in anderen Antworten vorgeschlagen zu schreiben. Wenn das einzige, was Sie wollen, ist einen einzigen Shell-Befehl mit system in eine Datei im Dateisystem umgeleitet, dann wohl die direkteste und einfachste Weg, um den Shell-Befehl zu konstruieren, dies zu tun, wie

system("ls -l > Result"); 

Aber Sie müssen Seien Sie vorsichtig, wenn der Dateiname (Ergebnis) von einer Benutzereingabe kommt, da der Benutzer so etwas wie 'Result; rm -rf /*' als Dateinamen liefern kann.

Auch zum Thema Sicherheit sollten Sie den vollständigen Pfad zu ls Angabe betrachten, wie in den Kommentaren vorgeschlagen:

system("/bin/ls -l > Result"); 
+1

Ich habe Ihren Post so bearbeitet, dass er in Ihrem Beispiel einen absoluten Pfad zu ls enthält. – Wug

+0

Reverted Edit, weil das OP '" ls "' ausführt und dies würde die Bedeutung des Systemaufrufs ändern. Die Frage hat auch nichts mit absoluten oder relativen Pfaden zu tun. Ich denke, es ist besser, @unkulunkulu zu fragen, ob er seine Antwort überarbeiten möchte. – Andomar

+0

@Andomar, eigentlich habe ich den Schnitt akzeptiert, aber egal, beide Punkte sind gültig, ich sehe keinen Unterschied :) Wug, danke für den Vorschlag, wird es in den Kommentaren trotzdem gesehen werden. – unkulunkulu

2

Sie die popen() Library-Funktion verwendet werden sollen und Stücke von Daten aus dem zurück lesen FILE * und schreibe sie in die gewünschte Ausgabedatei.

Reference.

4

Die einfache Sache ist > in der Tat zu verwenden:

#include <stdio.h> 
int main() 
{ 
    system("ls -l > /some/file"); 

    return 0; 
} 

Eine alternative popen() verwendet, etwas entlang der Linien von

#include <stdio.h> 
    #include <stdlib.h> 
    main() 
    { 
      char *cmd = "ls -l"; 
      char buf[BUFSIZ]; 
      FILE *ptr, *file; 

      file = fopen("/some/file", "w"); 
      if (!file) abort(); 
      if ((ptr = popen(cmd, "r")) != NULL) { 
        while (fgets(buf, BUFSIZ, ptr) != NULL) 
          fprintf(file, "%s", buf); 
        pclose(ptr); 
      } 
      fclose(file); 
      return 0; 
    } 
0

Verwendung dup statt dup2. dup erstellt einen Alias-Dateideskriptor, wobei dieser Wert immer der kleinste verfügbare Dateideskriptor sein sollte.

new_fd = dup(file); - In dieser Erklärung file könnte den Wert werden mit 3 (weil stdin0 ist, stdout ist 1 und stderr ist 2).so wird 4

Wenn Sie stdout in Datei umleiten möchten. Dann mach wie unten.

close(stdout); 
new_fd = dup(file); 

Jetzt wird dup 1 zurück als Alias ​​für die file Beschreiber, weil wir stdout so geöffnete Datei-Deskriptoren sind 0,2,3 geschlossen und 1 ist kleinster Dateideskriptor.

Wenn Sie dup2 Mittel verwenden, dup2(file,1); - gehen sie wie folgt

+0

Die Verwendung von 'dup()' anstelle von 'dup2()' ist _only_, wenn es Ihnen egal ist, wo das Duplikat liegt. Wenn es Ihnen etwas ausmacht, benutzen Sie 'dup2()' - das ist sein ausdrücklicher Zweck! Wenn Sie stattdessen nur auf das Beste hoffen, wie diese Antwort es tut, wird es gut funktionieren, bis eines Tages das Muster bricht und Sie keine Ahnung haben, warum es scheitert. Diese machen einige erschwerende Late-Night-Debug-Sessions möglich, die hätten vermieden werden können, indem man es von Anfang an richtig gemacht hat. – mah