automatically send stdin to interactive bash script - bash

I have a compiled program which i run from the shell; as i run it, it asks me for an input file in stdin. I want to run that program in a bash loop, with predefined input file, such as
for i in $(seq 100); do
input.txt | ./myscript
done
but of course this won't work. How can I achieve that? I cannot edit the source code.

Try
for i in $(seq 100); do
./myscript < input.txt
done
Pipes (|) are inter-process. That is, they stream between processes. What you're looking for is file redirection (e.g. <, > etc.)
Redirection simply means capturing output from a file, command,
program, script, or even code block within a script and sending it as
input to another file, command, program, or script.
You may see cat used for this e.g. cat file | mycommand. Given the above, this usage is redundant and often the winner of a 'Useless use of cat' award.

You can use:
./myscript < input.txt
to send content of input.txt on stdin of myscript

Based on your comments, it looks like myscript prompts for a file name and you want to always respond with input.txt. Did you try this?
for i in $(seq 100); do
echo input.txt | ./myscript
done
You might want to just try this first:
echo input.txt | ./myscript
just in case.

Related

Avoid capturing input on a script that stores output of command and functions

I have a script that stores the output of commands, functions, and other scripts in a log file.
I want to avoid capturing user input.
The line that is in charge of storing the output of the commands to a logfile is this one:
$command 2>&1 | tee /dev/tty | ruby -pe 'print Time.now.strftime("[%s] ") if !$stdin.tty?' >> "$tempfile"
If the command is a function or a script that asks for user input and prints out those data, that input is stored in temporary file. I would like to avoid that since I don't want to capture sensible data.
I can't modify the commands, functions that I'm wrapping.
Your command only saves program output, not user input. The problem you're seeing is that the command has chosen to output whatever the user inputs, merging it into its own output that is then obviously logged.
There is no good way around this. Please fix your command.
Anyways. Here's a bad, fragile, hacky way around it:
tempfile=test.txt
command='read -ep Enter_some_input: '
$command 2>&1 |
tee /dev/tty |
python3 -c $'import os\nwhile s:=os.read(0, 1024):\n if len(s) > 3: os.write(1, s)' |
ruby -pe 'print Time.now.strftime("[%s] ") if !$stdin.tty?' >> "$tempfile"
The Python command drops all reads of 3 bytes or less. This aims to remove character by character echo as would happen in the most basic cases of a user typing into readline and similar, while hopefully not removing too much intentional output.

Procmail - passing body to bash script

I have one liner mails that I wish to send from procmail into a bash script. I only want the body to be sent, nothing else.
Currently my .procmailrc looks like this:
:0
*^ Subject.*Xecute Command$
{
:0 bf
| /bin/bash /path/to/script
}
And my Bash script is simple:
#!/bin/bash
echo -e "\rLT 4>$0\r\r" > /dev/ttyS1
I don't get any input or output from anywhere.
Any pointers?
If the intention is to add some decorations to the email message and print it to a serial port (?), try a recipe like
:0b
*^ Subject.*Xecute Command$
| ( printf '\rLT 4>'; cat -; printf '\r\r' ) > /dev/ttyS1
The b flag applies to the action line if the condition matches, so you don't need the braces and a new conditionless recipe; the f flag makes no sense at all in this context. (Though if you want to keep the message for further processing, you'll want to add a c flag.)
Also, for the record, $0 in Bash is the name of the currently running script (or bash itself, if not running a script), and $# is the list of command-line arguments. But Procmail doesn't use either of these when it pipes a message to a script; it is simply being made available on standard input.
If you want the action in an external script, that's fine, too, of course; but a simple action like this is probably better written inline. You don't want or need to specify bash explicitly if the script file is executable and has a proper shebang; the reason to have a shebang is to make the script self-contained.
In response to comments, here is a simple Perl script to extract the first line of the first body part, and perform substitutions.
perl -nle 'next if 1../^$/;
s/\<foo\>/bar/g;
print "\rLT 4>$_\r\r"; exit(0)'
This would not be hard to do in sed either, provided your sed understands \r.
Write your script like that:
{
echo -e "\rLT 4>"
cat
echo -e "\r\r"
} > /dev/ttyS1
formail is your friend!
Pipe the message into:
:0
*^ Subject.*Xecute Command$
| formail -I "" | your-bash-script

How to wrap piped input to stdout in a bash script?

I want to write a bash script that will wrap piped input with some text.
Based on Googling and trying to pick from examples.
Here is what I have so far, that does not work:
#!/bin/sh
if readlink /proc/$$/fd/0 | grep -q "^pipe:"; then
echo "{ "template":{"name":"contact sheet template","root":"root","parameters": ["pages"]},"pages":"
cat
echo "}"
fi
I am receiving a JSON list from another program as piped input and I want to output before and afterwards with the above text before I pipe the results to the next program.
program_1 | wrapper.sh | program_2 > outputfile
But it doesn't output anything.
Can someone with more bash expertise point me in the right direction?
Personally I'll search in this way :
myscript.sh
echo 'BEFORE' $(cat) 'AFTER'
Do you mean your script is reading standard input from a pipe, such as
$ other-process | my-script
?
Then the commands in your script will simply inherit standard input from the pipe
#!/bin/sh
# Output preamble
cat <<EOF
{ "template":{"name":"contact sheet template","root":"root","parameters": ["pages"]},"pages":
EOF
cat # This reads from standard input inherited from your script
# Output the closing
cat <<EOF
}
EOF

piping in linux

i have a file called test which contains the word "hello" in it.
shouldn't
echo test | cat
output hello? since its taking the output from the echo test, which is test, as the input for cat. so essentially im doing cat test.
but the actual output is test, im really confused.
Your pipes sends test to cat as the input, not as the argument. You could do:
cat `echo test`
to control the argument to cat with echo.
echo prints its arguments. cat prints a file which is by default standard input. When you pipe echo's standard output is connected to cat's standard input.
Correct is simply cat test.
From cat --help
If no FILE or when FILE is -, read standard input.
In your case, cat reads from stdin, which is test and outputs that.
In some cases you might want the argument to be passed through the pipe. This is how you would do that:
echo test | xargs cat
which will output the contents of the file named "test".

Temporary Input Redirection in Bash

I am looking for a way to dump input into my terminal from a file, but when EOF is reached I would like input returned back to my keyboard. Is there a way to do this with Bash (or any other commonly-available *nix shell)?
Details:
I am debugging a server program which executes a fork to start a child process. Every time I start a debugging session with gdb I have to type set follow-fork-mode child. I would like to use some sort of input redirection to have this pre-populated. There are other uses as well that I can think of, so I'd prefer a general solution - hence the reason this question is not about gdb.
Solution:
start-server.sh
#!/bin/bash
cat run-server.txt - |/bin/bash
run-server.txt
gdb ./Server
set follow-fork-mode child
run
You can do this:
cat input_file - | program
That will concatenate input_file followed by stdin to program, which I think is what you want.
maybe expect is what you want
Maybe use an intermediate file? Assuming you want to run the script myscript.sh:
INPUT_FILE=input.txt
TEMP_FILE=`mktemp -t input`
myscript.sh < $TEMP_FILE &
cat $INPUT_FILE >> $TEMP_FILE
cat >> $TEMP_FILE

Resources