Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

redirecting output to a file in C

Tags:

linux

shell

i coded a basic shell in C for executing basic commands it'll execute commands ls, ls -al , ls -al | more etc.

i want to execute following command in my shell. like ;

ls -al > a.txt

this will give me a.txt file which contain output of ls -al process. i found a one solution, it's changing the command in my shell like [command1] | tee [filename]. in this instance it'll change ls -al > a.txt to ls -al | tee a.txt. but this process gives the output to file and terminal as well. how to stop printing output in terminal.

or are there are any better solution rather than using tee command. thanks in advance...

like image 979
Zeemaan Avatar asked Dec 15 '11 07:12

Zeemaan


People also ask

What is output redirection in C?

Before the C shell executes a command, it scans the command line for redirection characters. These special notations direct the shell to redirect input and output. You can redirect the standard input and output of a command with the following syntax statements: Item.

Which redirection operator redirects output to a file?

The > symbol is known as the output redirection operator. The output of a process can be redirected to a file by typing the command followed by the output redirection operator and file name.

How do I change stdout to a file?

Redirecting stdout and stderr to a file: The I/O streams can be redirected by putting the n> operator in use, where n is the file descriptor number. For redirecting stdout, we use “1>” and for stderr, “2>” is added as an operator.


2 Answers

This is the result of my testing things out with dup2

The more subtle point is remembering fflush at the right times :) Otherwise, you'll get very surprising results.

Also, prefer fileno instead of hardcoding 1 (stdout) 2 (stderr).

Redirecting stdin was left as an exercise for the reader

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

int main(int argc, const char *argv[])
{
    int out = open("cout.log", O_RDWR|O_CREAT|O_APPEND, 0600);
    if (-1 == out) { perror("opening cout.log"); return 255; }

    int err = open("cerr.log", O_RDWR|O_CREAT|O_APPEND, 0600);
    if (-1 == err) { perror("opening cerr.log"); return 255; }

    int save_out = dup(fileno(stdout));
    int save_err = dup(fileno(stderr));

    if (-1 == dup2(out, fileno(stdout))) { perror("cannot redirect stdout"); return 255; }
    if (-1 == dup2(err, fileno(stderr))) { perror("cannot redirect stderr"); return 255; }

    puts("doing an ls or something now");

    fflush(stdout); close(out);
    fflush(stderr); close(err);

    dup2(save_out, fileno(stdout));
    dup2(save_err, fileno(stderr));

    close(save_out);
    close(save_err);

    puts("back to normal output");

    return 0;
}
like image 62
sehe Avatar answered Sep 24 '22 03:09

sehe


Don't use pipe when the output is to go to a file.

When you fork the child to run the ls command, you note the redirection, and open the file; you then use dup2() (or close() and dup()) so that the file descriptor is now standard output for the child; you close the duplicated file descriptor - the one returned by open(); then you execute ls as usual; its standard output is now sent to the file.

Note that you do the non-pipe I/O redirection after forking, not before. Pipes have to be set up before forking, but other I/O redirection does not.

like image 35
Jonathan Leffler Avatar answered Sep 24 '22 03:09

Jonathan Leffler