Bash: Read Stdin from File and Write Stdout to File

Bash: read stdin from file and write stdout to file

Let's forget about top, that appears to be a red herring.

To map stdin or stdout to files, you can use redirection:

some_program < input_file          # Redirects stdin

another_program > output_file # Redirects stdout

or even:

yet_another  < input_file > output_file

Redirect stdout and stdin to file

Working off the responses here, I came up with this:

d=`tty`
exec >b.txt <b.txt
echo a
read c
exec >$d <$d

I also realized that it might be better to leave stdout and stdin alone:

exec 3>b.txt 4<b.txt
echo a >&3
read c <&4

Using the same file for stdin and stdout with redirection

The shell is what clobbers your output file, as it's preparing the output filehandles before executing your program. There's no way to make your program read the input before the shell clobbers the file in a single shell command line.

You need to use two commands, either moving or copying the file before reading it:

mv file.txt filecopy.txt
./myprog < filecopy.txt > file.txt

Or else outputting to a copy and then replacing the original:

./myprog < file.txt > filecopy.txt
mv filecopy.txt file.txt

If you can't do that, then you need to pass the filename to your program, which opens the file in read/write mode, and handles all the I/O internally.

./myprog file.txt                 # reads and writes according to its own rules

Redirect stdin to read from file while keeping stdin as input in Bash

cat can read from multiple files, including standard input using the name "-":

cat inputs.txt - | ./myprogram

If ./myprogram needs to run in the current shell, things get trickier. You can use process substitution:

./myprogram < <(cat inputs.txt -)

or a named pipe:

mkfifo p
cat inputs.txt - > p &
./myprogram < p

Reading from STDIN, performing commands, then Outputting to STDOUT in Bash

Use this:

temp=$(sed 's/the/THE/' <<<"$temp")

or

temp=$(printf "%s" "$temp" | sed 's/the/THE/')

You were telling sed to process a file named temp, not the contents of the variable $temp. You also weren't saving the result anywhere, so echo "$temp" simply prints the old value

How to read from a file or standard input in Bash

The following solution reads from a file if the script is called with a file name as the first parameter $1 and otherwise from standard input.

while read line
do
echo "$line"
done < "${1:-/dev/stdin}"

The substitution ${1:-...} takes $1 if defined. Otherwise, the file name of the standard input of the own process is used.

Redirect copy of stdin to file from within bash script itself

Maybe it'd be easier to use the script command? You could either have your users run the script with script directly, or do something kind of funky like this:

#!/bin/bash

main() {
read -r -p "Input string: "
echo "User input: $REPLY"
}

if [ "$1" = "--log" ]; then
# If the first argument is "--log", shift the arg
# out and run main
shift
main "$@"
else
# If run without log, re-run this script within a
# script command so all script I/O is logged
script -q -c "$0 --log $*" test.log
fi

Unfortunately, you can't pass a function to script -c which is why the double-call is necessary in this method.

If it's acceptable to have two scripts, you could also have a user-facing script that just calls the non-user-facing script with script:

script_for_users.sh
--------------------
#!/bin/sh
script -q -c "/path/to/real_script.sh" <log path>
real_script.sh
---------------
#!/bin/sh
<Normal business logic>


Related Topics



Leave a reply



Submit