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
How to Read the Mouse Button State from /Dev/Input/Mice
How Does Execve Call Dynamic Linker/Loader (Ld-Linux.So.2)
Accessing the Gpio (Of a Raspberry Pi) Without ''Sudo''
Cpu Affinity Masks (Putting Threads on Different Cpus)
Set Environment Variable with Space in Linux
Gdb Break When Program Opens Specific File
Case-Insensitive Glob on Zsh/Bash
How to Export Symbols from a Shared Library
How to Change a Certain Field of a File into Upper-Case Using Awk
Setting CPU Affinity of a Process from the Start on Linux
How to Specify Non-Capturing Groups in Sed
Need to Get the Dates of All Mondays in a Year
How to Find the Main Function's Entry Point of Elf Executable File Without Any Symbolic Information
Building a Simple (Hello-World-Esque) Example of Using Ld's Option -Rpath with $Origin
Replace a Text with a Variable
Docker Not Responding to Ctrl+C in Terminal
Sharing Devices (Webcam, Usb Drives, etc) with Docker
How to Generate Plain-Text Source-Code PDF Examples That Work in a Document Viewer