Rafael Baptista
Rafael Baptista

Reputation: 11499

How to redirect stdin to file in bash

Consider this very simple bash script:

#!/bin/bash
cat > /tmp/file

It redirects whatever you pipe into it to a file. e.g.

echo "hello" | script.sh

and "hello" will be in the file /tmp/file. This works... but it seems like there should be a native bash way of doing this without using "cat". But I can't figure it out.

NOTE:

  1. It must be in a script. I want the script to operate on the file contents afterwards.

  2. It must be in a file, the steps afterward in my case involve a tool that only reads from a file.

  3. I already have a pretty good way of doing this - its just that it seems like a hack. Is there a native way? Like "/tmp/file < 0 " or "0> /tmp/file". I thought bash would have a native syntax to do this...

Upvotes: 27

Views: 58129

Answers (8)

A very good idea: How to read hidden input from terminal and pipe it to another command

If you define an alias:

alias readp='{ read -s -p "Input a secret: "; printf %s $REPLY; }'

then you can do readp | wc -c

Upvotes: 0

Mapmo
Mapmo

Reputation: 1

If you don't want the program to end after reaching EOF, this might be helpful.

#!/bin/bash
exec < <(tail -F /tmp/a)
cat -

Upvotes: 0

Speedstone
Speedstone

Reputation: 413

Another option: dd of=/tmp/myfile/txt

Note: This is not a built-in, however, it might help other people looking for a simple solution.

Upvotes: 5

dee
dee

Reputation: 599

You could simply do

cp /dev/stdin  myfile.txt

Terminate your input with Ctrl+D or Ctrl+Z and, viola! You have your file created with text from the stdin.

Upvotes: 59

fork2execve
fork2execve

Reputation: 1650

I don't think there is a builtin that reads from stdin until EOF, but you can do this:

#!/bin/bash
exec > /tmp/file
while IFS= read -r line; do
  printf '%s\n' "$line"
done

Upvotes: 8

culmat
culmat

Reputation: 1216

echo "$(</dev/stdin)" > /tmp/file

terminate your input with ENTERctrl+d

Upvotes: 18

anubhava
anubhava

Reputation: 786091

Another way of doing it using pure BASH:

#!/bin/bash

IFS= read -t 0.01 -r -d '' indata

[[ -n $indata ]] && printf "%s" "$indata" >/tmp/file

IFS= and -d '' causes all of stdin data to be read into a variable indata.

Reason of using -t 0.01: When this script is called with no input pipe then read will timeout after negligible 0.01 seconds delay. If there is any data available in input it will be read in indata variable and it will be redirected to >/tmp/file.

Upvotes: 3

ikrabbe
ikrabbe

Reputation: 1929

Why don't you just

GENERATE INPUT | (
    # do whatever you like to the input here
)

But sometimes, especially when you want to complete the input first, then operate on the modified output, you should still use temporary files:

TMPFILE="/tmp/fileA-$$"
GENERATE INPUT | (
    # modify input
) > "$TMPFILE"
(
     # do something with the input from TMPFILE
) < "$TMPFILE"
rm "$TMPFILE"

Upvotes: 0

Related Questions