63

I have a script that process a folder, and count the files in the mean time.

i=1
find tmp -type f | while read x
do 
   i=$(($i + 1))
   echo $i
done
echo $i

However, $i is always 1, how do I resolve this?

1

2 Answers 2

79

In your example the while-loop is executed in a subshell, so changes to the variable inside the while-loop won't affect the external variable. This is because you're using the loop with a pipe, which automatically causes it to run in a subshell.

Here is an alternative solution using a while loop:

i=1
while read x; do
   i=$(($i + 1))
   echo $i
done <<<$(find tmp -type f)
echo $i

And here is the same approach using a for-loop:

i=1
for x in $(find tmp -type f);
do 
   i=$(($i + 1))
   echo $i
done
echo $i

For more information see the following posts:

Also look at the following chapter from the Advanced Bash Scripting Guide:

6
  • 2
    regarding the first solution, isn't it process substitution like so < <(find ...) instead of like so <<<(find ...) .... yours is the latter and that seems incorrect. Commented Jun 22, 2018 at 3:47
  • @AlexanderMills The <<< operator is called a here-string.
    – igal
    Commented Feb 17, 2019 at 22:11
  • 1
    solution using for-loop doent work if the output contains spaces; but while-loops works Commented Sep 23, 2019 at 10:54
  • 2
    A simpler version of <<<$( is < <(. Using here documents causes problems. E.g. they ignore NULL bytes, like when the command find … -print0 is used.
    – anon
    Commented Jun 13, 2022 at 23:20
  • 1
    This answer solves the immediate issue of allowing i to survive past the end of the loop, but does not address the other issues still in the code. Also, note that if the user wants the last value found by find, there are better ways to do this that would not break due to the presence of whitespaces in pathnames.
    – Kusalananda
    Commented Mar 25, 2023 at 14:58
10
i=1
while read x
do
   i=$(($i + 1))
   echo $i
done < <(find tmp -type f)
echo $i

https://stackoverflow.com/questions/7390497/bash-propagate-value-of-variable-to-outside-of-the-loop

1
  • 1
    This would solve the immediate issue of allowing the variable i to survive past the end of the loop, but the answer does not explain why this works. Also, correcting the many other issues still present in the code would be trivial.
    – Kusalananda
    Commented Mar 25, 2023 at 14:53

Not the answer you're looking for? Browse other questions tagged .