This question already has answers here:
rewinding stdin in a bash script
(4 answers)
Closed 7 years ago.
I have a shell script where I pass a txt file to the script as follows:
./run.sh < list.txt
Within the script, I am doing a "while read LIST do ... end"
It all works well, and the script executes using the list.
However, now I want to have a second while read LIST do ... end in the same shell script. I want it to read again from the original list I'm passing it on execution, but it doesn't work. It reads the list.txt file for the first loop, but not the second.
What do I do to make the script read list.txt each time I'm asking for it?
You can't read stdin twice. Try passing list.txt on the command-line rather than redirecting it.
./run.sh list.txt
Then in your script:
while read LINE; do
...
done < "$1"
while read LINE; do
...
done < "$1"
Alternatively, save the contents of stdin off the first time you read through it. For instance:
# First loop, save stdin in an array.
LINES=()
while read LINE; do
LINES+=("$LINE")
...
done
# Second loop, iterate over the array.
for LINE in "${LINES[#]}"; do
...
done
Related
This question already has answers here:
Looping through the content of a file in Bash
(16 answers)
Closed 1 year ago.
Absolute beginner here.
I have a list of passwords in a file named "pw.prn".
Welcome99
ABCDEFGH
12545678
lakers2021
gododgers
I wish to run each line in the file against a hashing program (mkpasswd -m sha-512) and output the password concatenated with a semi-colon then results of the hashing process to a new file:
So the output would look like this:
Welcome99:$6$xDb6xNDzqtnwzVLz$LMA3CNodueIyZavW3CIGDdcl19cekNNG8EB5Hc/vMzZGUSRhbueNCkYRlyaGKAb/VjW0cBiCHdJLt4iL08gBn/
ABCDEFGH:$6$mANzCeK.SUgSD$ID/E6NYPp4cddHCevI.yua3HotbA/a7fZ7xjSk7dUI6fayuTMsO9SCdSA7MFcgh8SUcmNqrqqE4IxAoIEcmFb0
12345678:$6$CwjNF9B1Q8bkwohy$N4eZcj6YPxxbA1MYz0k9t96nCcj9VsZmzrvgqTd9tp2yXbzAdb3hWyjBq6nquMwFbKMJw9ZXs3Uqj.gfnozUS0
lakers2021:$6$fENvTJijoQgyjWMo$W37vZ364wQugW.W7k9Gl8OfJLl8DfR3tpFO/O4oPTCazJgNkJfNE4WiP4z8qSM8H1.ZJrMUWVAYdYOxt0GSHG1
gododgers:$6$1JdXTdpguO0$ZwFoDtZZ2byDemiLv5JAuea6ucAdtYQUTC4EppX2PMzSLaYtMm/ENpBZZAy70Ceuu6yAjXYtggrSOINTRWoBi0
Unfortunately, I have no "code that I have tried" as I do not even know where to being. Is this a for loop? While? I have tried searching using bash script with interactive answers from a file but have not been able to piece anything together.
I hope that my example provides enough information to understand what I am looking for.
I am running this on Ubuntu Linux
Thank You
You could use a while + read loop. See How can I read a file (data stream, variable) line-by-line (and/or field-by-field)
Something like.
#!/usr/bin/env bash
while IFS= read -r line; do
printf '%s:%s\n' "$line" "$(mkpasswd -m sha-512 "$line")"
done < pw.prn
In bash script how do I reference a file as the input for an interactive prompt
Use a variable (positional parameter "$1")
#!/usr/bin/env bash
while IFS= read -r line; do
printf '%s:%s\n' "$line" "$(mkpasswd -m sha-512 "$line")"
done < "$1"
Then
./myscript pw.prn
Assuming the name of the script is myscript and the file in question is pw.prn
This question already has answers here:
Loop through an array of strings in Bash?
(21 answers)
Closed 2 years ago.
The following is the sample while loop.
res=()
lines=$'first\nsecond\nthird'
while read line; do
res+=("$line")
done <<< "$lines"
echo $res
When i run this directly in terminal im getting the following out put.
first second third
But when run the same script by saving it to a file. Then im getting the following out put.
first
Why is it behaving differently?
Note: I tested with and without shebang in file. result is same.
If you have a string with embedded newlines and want to turn it into an array split on them, use the mapfile builtin:
$ mapfile -t res <<<$'first\nsecond\nthird'
$ printf "%s\n" "${res[#]}"
first
second
third
This question already has answers here:
Output for loop to a file
(4 answers)
Loop and append/write to the same file without overwriting
(2 answers)
Closed 5 years ago.
I have a shell script that extracts certain values from a text file (input to it via the terminal). The script does the extraction as intended except, it doesn't print the output to the file correctly.
The script is:
#!/bin/bash
input_file=$1
while read -r LINE
do
IFS="=" read -r -a params <<< "$LINE"
if [ -n "${params[2]}" ]
then
IFS=" " read -r -a param_opcode <<< "${params[2]}"
echo "${param_opcode}"
fi
done < "$input_file"
The output on the terminal is as follows:
0xd2800140
0xd2800061
0x8b010000
0x8b000042
0xd1000821
0xd28001e5
0xd28000a6
0x9ac608a5
0xe7ff0010
0xe7ff0010
However, when I try to write this to a text file bu doing:
echo "${param_opcodes}" > log.txt
It prints only this to the file:
0xe7ff0010
I tried >> but I don't want to append to it. I want the file to be overwritten every time, I run the script.
Your redirection to log file isn't right because it's inside the while loop.
Use the redirection at the end of the while loop:
while read -r LINE; do
...
done < "$input_file" > "log.txt"
This question already has an answer here:
Why command "read" doesn't work?
(1 answer)
Closed 6 years ago.
I am trying to get a user input inside a while loop in a shell script.
ls| while read p
do
echo $p
read key
done
I cannot read the input from stdin(keyboard) because my input is piped through ls.
Can someone help me to get a user input inside the loop?
You can read from stdin using file descriptor 0. or by just using /dev/tty . Where $$ is pid of your current process.
ls| while read p
do
echo $p
read key < /proc/$$/fd/0
# OR read key < /dev/tty
done
This question already has answers here:
While loop stops reading after the first line in Bash
(5 answers)
Closed 2 years ago.
I am trying to execute a simple script to capture multiple server's details using svmatch on server names input from a file.
#!/bin/sh
while read line; do
svmatch $line
done < ~/svr_input;
The svmatch command works with no problem when executed as a stand along command.
Redirect your inner command's stdin from /dev/null:
svmatch $line </dev/null
Otherwise, svmatch is able to consume stdin (which, of course, is the list of remaining lines).
The other approach is to use a file descriptor other than the default of stdin:
#!/bin/sh
while IFS= read -r line <&3; do
svmatch "$line"
done 3<svr_input
...if using bash rather than /bin/sh, you have some other options as well; for instance, bash 4.1 or newer can allocate a free file descriptor, rather than requiring a specific FD number to be hardcoded:
#!/bin/bash
while IFS= read -r -u "$fd_num" line; do
do-something-with "$line"
done {fd_num}<svr_input