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...
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.
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.
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.
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;
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With