I am trying to find the pathname with the most characters in it. There might be better ways to do this. But I would like to know why this problem occurs.
LONGEST_CNT=0 find samples/ | while read line do line_length=$(echo $line | wc -m) if [[ $line_length -gt $LONGEST_CNT ]] then LONGEST_CNT=$line_length LONGEST_STR=$line fi done echo $LONGEST_CNT : $LONGEST_STR
It somehow always returns:
0 :
If I print the results for debugging inside the while loop the values are correct. So why bash does not make these variables global?
Shell variables are stored in the memory of the running shell. Use any data structure that lets you easily look up an item given its name; a hash table is a good choice. The difference between shell variables and environment variables is that environment variables are placed in the environment of subprocesses.
bash (or Posix shells in general) don't have an explicit syntax for a post-test loop (commonly known as a "do-while" loop) because the syntax would be redundant.
break exits from a for, select, while, or until loop in a shell script. If number is given, break exits from the given number of enclosing loops. The default value of number is 1 . break is a special built-in shell command.
When you pipe into a while
loop in Bash, it creates a subshell. When the subshell exits, all variables return to their previous values (which may be null or unset). This can be prevented by using process substitution.
LONGEST_CNT=0 while read -r line do line_length=${#line} if (( line_length > LONGEST_CNT )) then LONGEST_CNT=$line_length LONGEST_STR=$line fi done < <(find samples/ ) # process substitution echo $LONGEST_CNT : $LONGEST_STR
The "correct" reply is given by Dennis. However, I find the process substitution trick extremely unreadable if the loop contains more than a few lines. When reading a script, I want to see what goes into the pipe before I see how it is processed.
So I usually prefer this trick of encapsulating the while loop in "{}".
LONGEST_CNT=0 find /usr/share/zoneinfo | \ { while read -r line do line_length=${#line} if (( line_length > LONGEST_CNT )) then LONGEST_CNT=$line_length LONGEST_STR=$line fi done echo $LONGEST_CNT : $LONGEST_STR }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With