This question already has answers here:
Propagate value of variable to outside of the loop [duplicate]
(3 answers)
A variable modified inside a while loop is not remembered
(8 answers)
Closed 5 months ago.
How do i keep a variable value after a while loop?
My intention here is to put a if clause within the while to count each time an operation has been done, but isn't working since the count resets after each while loop.
count=0
for file in $(ls /path)
do
cat $ file | while read line
do
count=$((count+1))
echo $count
done
done
echo $count #This echoes 0, even though the inner echo shows each sum.
There are many methods. In this case, it's probably easiest to drop the UUOC:
while read line; do
count=$((count+1))
echo "$count"
done < "$file"
which would be better written:
while read line; do echo "$((++count))"; done < "$file"
which would be even better written:
count=$(wc -l < "$file")
Although the last version sets count accurately (which the first two do not unless count is initialized) and does not emit the counts.
Related
This question already has answers here:
A variable modified inside a while loop is not remembered
(8 answers)
Closed 1 year ago.
I can't find my answer anywhere. The counter in my code doesn't work. Why and what to do ?
count=0;
for file1 in folder1;
do
cat $file1 | while read line
do
echo $line;
((count++));
done
done
echo "Count : ${count}";
When using a pipeline, the commands are executed in a subshell. Changes in a subshell don't propagate to the parent shell, so the counter is never incremented.
You don't need a pipeline here. Use a redirection instead:
count=0
while read line
do
echo $line;
((count++));
done < "$file1"
This question already has answers here:
Shell script while read loop executes only once
(6 answers)
While loop stops reading after the first line in Bash
(5 answers)
Bash script stops execution of ffmpeg in while loop - why?
(3 answers)
Closed 5 years ago.
I have a while loop that should iterate over a text file but stops at the first line and I can't figure out why. My code is below.
while read hadoop_accounts; do
if ! grep "no lock no remove"; then
echo "${hadoop_accounts%%:*}"
echo "${hadoop_accounts%%:*}" >> missing_no_lock_no_remove.txt
fi
done < hadoop_accounts.txt
When grep is run with no explicit redirection or file to read, it reads stdin. All of stdin. The same stdin your while read loop is reading from.
Thus, with all your stdin consumed by grep, there's nothing left for the next read command to consume.
The easy approach (and much better for performance) is to do the substring check internal to the shell, and not bother starting up a new copy of grep per line processed at all:
while IFS= read -r hadoop_accounts; do
if ! [[ $hadoop_accounts = *"no lock no remove"* ]]; then
echo "${hadoop_accounts%%:*}"
echo "${hadoop_accounts%%:*}" >&3
fi
done < hadoop_accounts.txt 3>> missing_no_lock_no_remove.txt
Note also that we're only opening the output file once, not re-opening it every single time we want to write a single line.
If you really want to call grep over and over and over with only a single line of input each time, though, you can do that:
while IFS= read -r hadoop_accounts; do
if ! grep "no lock no remove" <<<"$hadoop_accounts"; then
echo "${hadoop_accounts%%:*}"
echo "${hadoop_accounts%%:*}" >&3
fi
done < hadoop_accounts.txt 3>> missing_no_lock_no_remove.txt
Or, even better than either of the above, you can just run grep a single time over the entire input file and read its output in the loop:
while IFS= read -r hadoop_accounts; do
echo "${hadoop_accounts%%:*}"
echo "${hadoop_accounts%%:*}" >&3
done < <(grep -v 'no lock no remove' <hadoop_accounts.txt) 3>>missing_flags.txt
This question already has answers here:
How do I iterate over a range of numbers defined by variables in Bash?
(20 answers)
Closed 7 years ago.
If I create a bash loop like this, using literal numbers, all works as expected:
#!/bin/bash
for i in {1..10}; do
echo $i
done
The output is:
1
2
3
4
5
6
7
8
9
10
But if I want to use the upper limit in a variable, I can't seem to get it it right. Here are my four attempts:
#!/bin/bash
n=10
for i in {1..$n}; do
echo $i
done
for i in {1.."$n"}; do
echo $i
done
for i in {1..${n}}; do
echo $i
done
for i in {1.."${n}"}; do
echo $i
done
And the output is now:
{1..10}
{1..10}
{1..10}
{1..10}
Not what I wanted... :(
To be clear about the question:
How do I use a variable as the limit for the range syntax in a bash for loop?
Don't use {...}; use a C-style for loop.
for ((i=1; i <= $n; i++)); do
Brace expansion occurs before parameter expansion, so you can't generate a variable-length sequence without using eval. This is also more efficient, as you don't need to generate a possibly large list of indices before the loop begins.
This question already has answers here:
Variables getting reset after the while read loop that reads from a pipeline
(3 answers)
Closed 7 years ago.
I have 3 lines in file /root/backuplist.txt.
The first echo prints perfectly, but the last one prints an empty line; I'm not sure why. Somehow, the $DIRS value is getting unset.
#!/bin/bash
cat /root/backuplist.txt |
while read line
do
DIRS+="$line "
echo $DIRS
done
echo $DIRS
Problem is use of pipe here, which is forking a sub-shell for your while loop and thus changes to DIRS are being made in the child shell that are not visible in the parent shell. Besides cat is unnecessary here.
Have it this way:
#!/bin/bash
while read -r line
do
DIRS+="$line "
echo "$DIRS"
done < /root/backuplist.txt
echo "$DIRS"
This question already has answers here:
While-loop subshell dilemma in Bash
(4 answers)
Closed 8 years ago.
I occured a problem and I can't find why does it run.
The follow codes is both used to count the line of file 'file.in' , but the first can't change the value of $line_count
The first code is :
#!/bin/bash
line_count=0
cat file.in | while read line; do
let ++line_count
done
echo $line_count
the second code is :
#!/bin/bash
line_count=0
while read line; do
let ++line_count
done < file.in
echo $line_count
Due to use of pipe your first code sample is executing while loop in a sub-shell hence changes made in line_count variable get lost after sub shell exits.