WeCodeAcademy

Step 5: Redirect output to a file

How does echo hi > out.txt work? The shell opens the file, then in the child uses dup2 to make the file become standard output (file descriptor 1) before exec. The program does not know: it just prints to "stdout" as always. O_TRUNC empties the file first, which is why > replaces content (while >> would append with O_APPEND).

ExampleC
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

// Run argv with its standard output sent to a file (like "echo hi > out.txt").
int run_redirected(char *argv[], const char *file) {
  fflush(stdout);
  pid_t pid = fork();
  if (pid == 0) {
    int fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd < 0) _exit(1);
    dup2(fd, STDOUT_FILENO);          // from now on, "stdout" IS the file
    close(fd);
    execvp(argv[0], argv);
    _exit(127);
  }
  int status;
  waitpid(pid, &status, 0);
  return WIFEXITED(status) ? WEXITSTATUS(status) : 1;
}

int main(void) {
  const char *file = "/tmp/tinyshell-out.txt";

  char *cmd1[] = { "echo", "first line", NULL };
  printf("status %d\n", run_redirected(cmd1, file));

  char *cmd2[] = { "echo", "second line replaces it", NULL };
  printf("status %d\n", run_redirected(cmd2, file));   // ">" truncates the file

  FILE *f = fopen(file, "r");
  char line[100];
  while (fgets(line, sizeof(line), f)) printf("file contains: %s", line);
  fclose(f);
  remove(file);
  return 0;
}
Output
status 0
status 0
file contains: second line replaces it

The second command replaced the first one's text: the file holds only the second line. The idea that "everything is a file descriptor" is one of Unix's most powerful designs.

Quick check

What does dup2(fd, STDOUT_FILENO) do?

Finish the quick check (and any code exercise) to complete this lesson, or mark it done yourself.

Tip: use the left and right arrow keys to move between lessons.