Infinite while loop in a BASH script. BASH: description of for, while, until loops and examples of use Example: searching for executable files


Author: Paul Cobbaut
Published date: October 16, 2014
Translation: A. Panin
Translation date: December 21, 2014

Chapter 22. Loops in Scripts

test command

The test command allows you to determine whether an expression is true or false. Let's start by testing whether the integer value 10 is greater than the integer value 55. $ test 10 -gt 55 ; echo $? 1$

The test command returns 1 if the expression is false. And, as you will see in the following example, the test command will return 0 if the expression evaluates to true. $ test 56 -gt 55 ; echo $? $0

If you are more comfortable working with the strings true and false, you can use the test command as shown below. $ test 56 -gt 55 && echo true || echo false true $ test 6 -gt 55 && echo true || echo false false

The test command can also be replaced by square brackets, so the commands in the example below are exactly the same as the commands in the example above. $ [ 56 -gt 55 ] && echo true || echo false true $ [ 6 -gt 55 ] && echo true || echo false false

Below are examples of implementations of some checks. Refer to the man test page for an overview of additional features implementation of various checks. [ -d foo ] Does directory foo exist? [ -e bar ] Does the bar file exist? [ "/etc" = $PWD ] Is /etc equivalent to the value of $PWD ? [ $1 != "secret" ] Is the value of the first script parameter different from the secret string? [ 55 -lt $bar ] Is the integer value 55 less than the value of $bar ? [ $foo -ge 1000 ] Is the value of $foo greater than or equal to the integer value 1000 ? ["abc"< $bar ] Будет ли строка abc расположена выше значения переменной $bar в списке после сортировки? [ -f foo ] Является ли foo обычным файлом? [ -r bar ] Является ли bar readable file? [ foo -nt bar ] Is foo newer than bar ? [ -o nounset ] Is the nounset shell option enabled?

Check operators can be combined with operators corresponding to logical operations"AND" and "OR". paul@RHEL4b:~$ [ 66 -gt 55 -a 66 -lt 500 ] && echo true || echo false true paul@RHEL4b:~$ [ 66 -gt 55 -a 660 -lt 500 ] && echo true || echo false false paul@RHEL4b:~$ [ 66 -gt 55 -o 660 -lt 500 ] && echo true || echo false true

Conditional jump if then else

The if then else construct is intended to select a code option. If a certain condition is true, some code will be executed, otherwise some other code will be executed. The example below checks for the existence of a file, after which, if the assumption of the existence of the file is confirmed, a corresponding message is displayed. #!/bin/bash if [ -f isit.txt ] then echo the file isit.txt exists! else echo file isit.txt not found! fi

In the event that we save this code script in a file named "choice", it can be executed in the same way. $ ./choice file isit.txt not found! $ touch isit.txt $ ./choice file isit.txt exists! $

Conditional jump if then elif

You can post new operator conditional jump if inside an else block using the elif operator. Below is a simple example of such an entry. #!/bin/bash count=42 if [ $count -eq 42 ] then echo "42 is a valid value." elif [ $count -gt 42 ] then echo "Too many." else echo "Not enough." fi

for loop

The example below shows the syntax of a classic for loop in the bash shell. for i in 1 2 4 do echo $i done

An example of using a for loop combined with an inline shell call. #!/bin/ksh for counter in `seq 1 20` do echo counting from 1 to 20, current value $counter sleep 1 done

A script completely similar to the one presented above can be created without using an embedded command shell by using the bash shell declaration for a range of values ​​(from value..to value). #!/bin/bash for counter in (1..20) do echo counting from 1 to 20, current value $counter sleep 1 done

This for loop uses a mechanism for searching files by pattern (implemented as part of the command expansion mechanism). If the above instructions are posted directly in command line, it will function similarly. kahlan@solexp11$ ls count.ksh go.ksh kahlan@solexp11$ for file in *.ksh ; do cp $file $file.backup ; done kahlan@solexp11$ ls count.ksh count.ksh.backup go.ksh go.ksh.backup

while loop

Below is a simple example of using a while loop. i=100; while [ $i -ge 0 ] ; do echo Countdown from 100 to 0, current value $i; let i--; done

Infinite loops can be implemented using while true or while: declarations, where the symbol: is the equivalent of the missing operation in the Korn shell and bash. #!/bin/ksh # endless loop while: do echo hello sleep 1 done

Until loop

Below is a simple example of using an until loop. let i=100; until [ $i -le 0 ] ; do echo Countdown from 100 to 1, current value $i; let i--; done

Practice: Tests and Loops in Scripts

3. Develop a script that will use a while loop to count from 3 to 7.

4. Develop a script that will use an until loop to count down from 8 to 4.

5. Develop a script that will count files with a .txt extension in the current directory.

6. Use the if statement in the created script to make it work correctly if there are no files with the .txt extension in the current directory.

The correct procedure for completing a practical task: checks and loops in scripts

1. Develop a script that will use a for loop to count from 3 to 7.

#!/bin/bash for i in 3 4 5 6 7 do echo Counting from 3 to 7, current value $i done

2. Develop a script that will use a for loop to count from 1 to 17000.

The bash shell supports for loops, which allow you to iterate over sequences of values. That's what it is basic structure such cycles:

For var in list do command done
In each iteration of the loop, the variable var will be written to the next value from list. The first pass of the loop will therefore use the first value from the list. In the second - the second, and so on - until the loop reaches the last element.

Iterating over simple values

Perhaps the simplest example of a for loop in bash scripts is iterating over a list of simple values:

#!/bin/bash for var in first second third fourth fifth do echo The $var item done
The results of this script are shown below. You can clearly see that the $var variable contains elements from the list sequentially. This happens until the cycle reaches the last of them.


Simple for loop

Please note that the $var variable retains its value when exiting the loop, its contents can be changed, and in general, you can work with it like any other variable.

Iterating over complex values

The list used to initialize the for loop can contain not only simple strings consisting of one word, but also entire phrases that contain several words and punctuation marks. For example, it might look like this:

#!/bin/bash for var in first "the second" "the third" "I’ll do it" do echo "This is: $var" done
This is what happens after this loop goes through the list. As you can see, the result is quite expected.


Iterating over complex values
TNW-CUS-FMP - promo code for a 10% discount on our services, available for activation within 7 days"

Initializing a loop with a list obtained from the results of the command

Another way to initialize a for loop is to pass it a list, which is the result of a command. Here command substitution is used to execute them and obtain the results of their work.

#!/bin/bash file="myfile" for var in $(cat $file) do echo " $var" done
This example uses the cat command, which reads the contents of a file. The resulting list of values ​​is passed into the loop and displayed on the screen. Please note that the file we are accessing contains a list of words separated by newlines; no spaces are used.


A loop that loops through the contents of a file

Here we must take into account that such an approach, if line-by-line data processing is expected, will not work for a file of a more complex structure, the lines of which may contain several words separated by spaces. The loop will process individual words, not lines.

What if this is not what you need at all?

Field separators

The reason for the above feature is the special environment variable, which is called IFS (Internal Field Separator) and allows you to specify field separators. By default, the bash shell considers the following characters to be field separators:
  • Space
  • Tab character
  • Line feed character
If bash encounters any of these characters in the data, it assumes that it is preceded by the next independent value in the list.

To resolve the issue, you can temporarily change the IFS environment variable. Here's how to do it in a bash script, assuming you only need a newline as a field separator:

IFS=$"\n"
Once you add this command to your bash script, it will work as expected, ignoring spaces and tabs and treating only newline characters as field separators.

#!/bin/bash file="/etc/passwd" IFS=$"\n" for var in $(cat $file) do echo " $var" done
If this script is run, it will output exactly what is required of it, giving, in each iteration of the loop, access to the next line written to the file.


Line by line traversal of a file in a for loop

Separators can also be other characters. For example, above we displayed the contents of the /etc/passwd file. User data on lines is separated by colons. If you need to process such strings in a loop, IFS can be configured like this:

Traversing files contained in a directory

One of the most common uses of for loops in bash scripts is to traverse files located in a directory and process those files.

For example, here's how to list files and folders:

#!/bin/bash for file in /home/likegeeks/* do if [ -d "$file" ] then echo "$file is a directory" elif [ -f "$file" ] then echo "$file is a file" fi done
If you understood the previous material in this series of articles, you should understand the structure of the if-then construct, as well as how to distinguish a file from a folder. If you find it difficult to understand the above code, re-read this material.

This is what the script will output.


Displaying the contents of a folder

Pay attention to how we initialize the loop, namely wildcard"*" at the end of the folder address. This symbol can be thought of as a wildcard meaning: “all files with any names.” it allows you to organize automatic substitution file names that match the pattern.

When testing a condition in an if statement, we enclose the variable name in quotes. This is done because the file or folder name may contain spaces.

C-style for loops

If you are familiar with the C programming language, the syntax for describing bash for loops may seem strange to you, since you are obviously used to describing loops this way:

For (i = 0; i< 10; i++) { printf("number is %d\n", i); }
In bash scripts you can use for loops, the description of which looks very similar to C-style loops, although there are some differences. The cycle diagram with this approach looks like this:

For ((initial value of variable; condition for ending loop; change of variable))
In bash it can be written like this:

For ((a = 1; a< 10; a++))
Here's a working example:

#!/bin/bash for ((i=1; i<= 10; i++)) do echo "number is $i" done
This code will output a list of numbers from 1 to 10.

Looping in C style

while loop

The for construct is not the only way to organize loops in bash scripts. You can also use while loops here. In such a loop, you can specify a command to check a certain condition and execute the body of the loop until the condition being tested returns zero, or a signal for the successful completion of a certain operation. When the loop condition returns a non-zero value, which means an error, the loop will stop.

Here is a diagram of the organization of while loops
while condition check command
do
other teams
done

Let's take a look at an example script with a loop like this:

#!/bin/bash var1=5 while [ $var1 -gt 0 ] do echo $var1 var1=$[ $var1 - 1 ] done
At the entrance to the loop, it is checked whether the variable $var1 is greater than zero. If so, the body of the loop is executed, in which one is subtracted from the value of the variable. This happens in each iteration, and we print the value of the variable to the console before it is modified. As soon as $var1 reaches the value 0, the loop stops.

Result of the while loop

If you do not modify the $var1 variable, this will cause the script to end up in an infinite loop.

Nested Loops

You can use any commands in the body of the loop, including launching other loops. Such constructions are called nested loops:

#!/bin/bash for ((a = 1; a<= 3; a++)) do echo "Start $a:" for ((b = 1; b <= 3; b++)) do echo " Inner loop: $b" done done
Below is what this script will output. As you can see, first the first iteration of the outer loop is executed, then three iterations of the inner one, after its completion the outer loop comes into play again, then the inner one again.

Nested Loops

Processing File Contents

Most often, nested loops are used to process files. So, the outer loop is iterating over the lines of the file, and the inner one is already working with each line. Here, for example, is what processing the /etc/passwd file looks like:

#!/bin/bash IFS=$"\n" for entry in $(cat /etc/passwd) do echo "Values ​​in $entry –" IFS=: for value in $entry do echo " $value" done done
There are two loops in this script. The first one traverses the lines using the newline character as a delimiter. The internal one is busy parsing strings whose fields are separated by colons.

File Data Processing

This approach can be used when processing CSV files, or any similar files, by writing the delimiter character into the IFS environment variable as needed.

Cycle management

Perhaps, after entering the loop, you will need to stop it when the loop variable reaches a certain value that does not correspond to the initially specified condition for ending the loop. In such a situation, will it be necessary to wait for the normal completion of the cycle? Of course not, and in such cases the following two commands will come in handy:
  • break
  • continue

break command

This command allows you to interrupt the execution of a loop. It can be used for both for and while loops:

#!/bin/bash for var1 in 1 2 3 4 5 6 7 8 9 10 do if [ $var1 -eq 5 ] then break fi echo "Number: $var1" done
Such a loop, under normal conditions, will go through the entire list of values ​​from the list. However, in our case, its execution will be interrupted when the $var1 variable is equal to 5.

Exiting a for loop early

Here is the same thing, but for the while loop:

#!/bin/bash var1=1 while [ $var1 -lt 10 ] do if [ $var1 -eq 5 ] then break fi echo "Iteration: $var1" var1=$(($var1 + 1)) done
The break command, executed when $var1 reaches 5, breaks the loop. The console will display the same thing as in the previous example.

continue command

When this command is encountered in the body of the loop, the current iteration ends early and the next one begins, without exiting the loop. Let's look at the continue command in a for loop:

#!/bin/bash for ((var1 = 1; var1< 15; var1++)) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done
When the condition inside the loop is satisfied, that is, when $var1 is greater than 5 and less than 10, the shell executes the continue command. This results in skipping the remaining commands in the body of the loop and moving on to the next iteration.

The continue command in a for loop

Processing Output Running in a Loop

Data output from a loop can be processed by either redirecting the output or passing it to a pipeline. This is done by adding output processing commands after the done statement.

For example, instead of showing on the screen what is output in a loop, you can write it all to a file or pass it somewhere else:

#!/bin/bash for ((a = 1; a< 10; a++)) do echo "Number is $a" done >myfile.txt echo "finished."
The shell will create the file myfile.txt and redirect the output of the for statement to that file. Let's open the file and make sure that it contains exactly what we expect.

Redirect loop output to file

Example: Search for executable files

Let's use what we've already covered and write something useful. For example, if you need to find out which executable files are available on the system, you can scan all the folders recorded in the PATH environment variable. We already have the entire arsenal of tools that we need for this, we just need to put it all together:

#!/bin/bash IFS=: for folder in $PATH do echo "$folder:" for file in $folder/* do if [ -x $file ] then echo " $file" fi done done
This script, small and simple, allowed us to get a list of executable files stored in folders from PATH.

Searching for executable files in folders from the PATH variable

Results

Today we talked about for and while loops in bash scripts, how to run them, and how to manage them. Now you know how to process strings with different delimiters in loops, you know how to redirect data output in loops to files, how to view and analyze the contents of directories.

If we assume that you are a developer of bash scripts who knows about them only what is stated in the first part of this series of articles, and in this second, then you can already write something useful. Ahead is the third part, after understanding which you will learn how to pass parameters and command line switches to bash scripts, and what to do with it all.

A brief description of the difference in loop types:

for - will perform an action as long as there are objects to execute (for example, reading a stream from stdin, a file or a function);
while - performs the action until condition is true;
until - will be executed as long as condition will not become true, i.e. for now it is false .

FOR Loop

Let's consider this version of the script with a loop:

$ cat loop.sh #!/bin/bash for variable in `ls -1` do echo "$variable" done

The syntax is very simple and is quite clearly shown in the example:

for (start the loop) variable (declare a variable on which we will perform actions) in (send a flow to the loop) `ls -1` (command to be executed and passed to the $variable variable). Do and done are the “body” of the loop, within which the main actions will be performed on the received data, and echo “$variable” is the actual action performed by the loop.

Now let’s change the example a little, and instead of explicitly specifying the command, we’ll use the second variable:

$ cat loop.sh #!/bin/bash ls=`ls -1` for variable in $ls do echo "$variable" done

Now the ls -1 command is passed in a separate variable, which allows you to work with the loop more flexibly. Instead of a variable in a loop, you can also use a function:

$ cat loop.sh #!/bin/bash lsl () ( ls -1 ) for variable in `lsl` do echo "$variable" done

The main condition of the for loop is that it will be executed as long as the command passed to it contains objects for action. Based on the example above - as long as ls -1 has files to display - the loop will pass them to a variable and execute the "loop body". As soon as the list of files in the directory ends, the loop will complete its execution.

Let's make the example a little more complicated.

The directory contains a list of files:

$ ls -1 file1 file2 file3 file4 file5 loop.sh nofile1 nofile2 nofile3 nofile4 nofile5

We need to select from them only those that do not have the word " no«:

$ cat loop.sh #!/bin/bash lsl=`ls -1` for variable in $lsl do echo "$variable" | grep -v "no" done $ ./loop.sh file1 file2 file3 file4 file5 loop.sh

You can also use conditional expressions in a loop ( conditional expressions) […] to check conditions and the break statement to interrupt the loop if the condition is triggered.

Consider this example:

$ cat loop.sh #!/bin/bash lsl=`ls -1` for variable in $lsl do if [ $variable != "loop.sh" ] then echo "$variable" | grep -v "no" else break fi done

The loop will continue until the file loop.sh is encountered. As soon as the execution of the loop reaches this file, the loop will be interrupted by the break command:

$ ./loop.sh file1 file2 file3 file4 file5

Another example is the use of arithmetic operations immediately before executing the body of the loop:

$ cat loop.sh #!/bin/bash for ((count=1; count<11; count++)) do echo "$count" done

Here we set three control commands - count=1, a controlling condition - while count is less than 11, and a command to execute - count +1:

WHILE and UNTIL loops

A simple example that clearly demonstrates how the while loop works:

$ cat loop.sh #!/bin/bash count=0 while [ $count -lt 10 ] do ((count++)) echo $count done

We set the $count variable to zero, and then run the whi le loop with the condition “while $count is less than ten, execute the loop.” In the body of the loop we execute postfix increment+1 to the $count variable and the result is printed to stdout.

Execution result:

$ ./loop.sh 1 2 3 4 5 6 7 8 9 10

As soon as the value of the $count variable became 10, the loop stopped.

A good example of an "infinite" loop that demonstrates how while works:

$ cat loop.sh #!/bin/bash count=10 while [ 1 = 1 ] do ((count++)) echo $count done $ ./loop.sh ... 5378 5379 5380 5381 5382 5383 ^C

The until loop works similarly, but in the opposite direction:

$ cat loop.sh #!/bin/bash count=0 until [ $count -gt 10 ] do ((count++)) echo $count done

Here we set a similar condition, but instead of “while the variable is less than 10,” we specify “until the variable becomes greater than 10.” Execution result:

$ ./loop.sh 1 2 3 4 5 6 7 8 9 10 11

If the above example of an “endless loop” is executed using until, it will not output anything, unlike while:

$ cat loop.sh #!/bin/bash count=10 until [ 1 = 1 ] do ((count++)) echo $count done $ ./loop.sh $

Because " condition"originally" true"—the body of the loop will not be executed.

Just like in the for loop, you can use functions in while and until. For example, a loop from a real-life script that checks the server status Tomcat(PID is taken from the system SLES, may differ in other systems), a slightly simplified version:

$ cat loop.sh #!/bin/bash check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(print $2)"` ) while check_tomcat_status do if [ -n "$ RUN" ] then printf "WARNING: Tomcat still running with PID $RUN." else printf "Tomcat stopped, proceeding...nn" break fi done

Execution result:

$ ./loop.sh WARNING: Tomcat still running with PID 14435 26548.WARNING: Tomcat still running with PID 14435 26548.WARNING: Tomcat still running with PID 14435 26548.WARNING: Tomcat still running with PID 14435 26548.WARNING: Tomcat still running with PID 14435 26548.WARNING: Tomcat still running with PID 14435 26548.WARNING: Tomcat still running with PID 14435 26548.WARNING: Tomcat still running with PID 14435

Full version:

Check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(print $2)"` ) while check_tomcat_status; do if [ -n "$RUN" ] then printf "WARNING: Tomcat is still running with PID $RUN. Stop it? " answer "Stopping Tomcat..." "Proceeding installation..." && $CATALINA_HOME/bin/shutdown. sh 2&>1 /dev/null || break sleep 2 if [ -n "$RUN" ] then printf "Tomcat still running. Kill it? " answer "Killing Tomcat..." "Proceeding installation...n" && kill $RUN || break sleep 2 fi else printf "Tomcat stopped, proceeding...nn" break fi done

The answer function was described in the article, but here a slightly improved version is used:

Answer () ( while read response; do echo case $response in |) printf "$1n" return 0 break ;; |) printf "$2n" return 1 break ;; *) printf "Please, enter Y(yes) or N(no)! " esac done )

Here it was possible to use both while and until - but not a for loop, since for would have worked once (received the PID and ended).

Loops are an extremely convenient thing when writing any programs or scripts, rather even necessary. They allow us to execute a certain section of code a specified number of times. Naturally, bash has several types of loops. We will describe the cycles for in, for, while, until. Although for in and for are considered different syntaxes of the same statement, in my opinion they differ from each other more than while from until.

Loop with counter for in:

Cycle for in This is a loop with a counter. The block of code located in the body of the loop is repeated as many times as there are values ​​contained in the list of the for in operator, and with each repetition, the counter variable (here it is called var, but of course you can call it whatever you like) has the value of the next element of the list.
If the keyword do is on the same line as the word for, then after the list of arguments (before do) you must put a semicolon.
Each of the elements<список>may contain several arguments. This is useful when processing groups of parameters. In this case, to force parsing of each of the arguments in<списке>, you must use the set instruction
You can use a variable as a list in a for loop.
IN<списке>The for loop can use file names, which in turn can contain wildcard characters. This can be very useful when working with a large number of files.
If<список>is not specified in the for loop, then the variable $@ is used as it - a list of command line arguments.
When creating a list of arguments, you can use command substitution in a for loop.
The output of the loop can be redirected from stdout to a file or somewhere else (you can learn more about this by looking at I/O redirection).

Syntax:
for var in<список>
do
<выполняемые команды>
done

Example:
for names in name1 name2 name3 name4
do
echo $names
done

Loop operator for has another way of writing - very similar to the syntax of the for operator in the C language. In this case, when initializing the counters, the initial values ​​of variables or one variable are set and after each pass of the loop the condition is checked, if the check returns true, then the next pass of the loop begins. In the block<приращение счётчиков>the value of our variable counters must necessarily change (not necessarily upward) so that when checking the condition, sooner or later we get the value false, otherwise the loop will never end. A very convenient and most importantly familiar option if any operation needs to be repeated a specified number of times.

With a similar syntax:
for ((<инициализация счётчиков>; <проверка условия>; <приращение счётчиков>))
do
<выполняемые команды>
done

Example:
for ((var=1; var<= LIMIT ; var++))
do
echo $var
done

while loop:

This is a fairly simple construction that checks the condition behind the operator while and if this condition is true, it executes the block of commands located between the words do and done and then again proceeds to checking the condition. If the check returns false, the cycle ends and the following commands begin to be executed: done. It is imperative to ensure that<проверка условия>depended on the code running in the loop; otherwise, if the result of the check does not change, you will get an infinite loop.
The standard input device for a while loop can be redirected to a file using the redirection command< в конце цикла.

Syntax:
while<Проверка условия>
do
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
done

Example:
while [ $var0 -eq 100 ]
do
echo $var
var++
done

Operator while may have several conditions. But only the last of them determines the possibility of continuing the cycle. In this case, the syntax of the loop operator will be different from the usual one.
Syntax(I repeat once again that only the last condition affects the execution of the loop) :
while
<условие1>
<условие2>

<условиеN>
do
<выполняемые команды - тело цикла>
done

Until loop:

Operator until is very similar to while, it also evaluates the condition, but executes the body of the loop if the result of the calculation is false. It may seem unusual, but until evaluates the condition before the first pass of the loop, like while, and not after it. As with for/in loops, when placing the do keyword on the same line as the loop declaration, you must insert a ";" character. before do.
As in the previous case, it is important to remember that the condition must depend on the operations in the loop body, otherwise our script will never complete.

Syntax:
until<Проверка условия>
do
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
done

Example:
until [ $var0 -gt 100] # The condition is checked at the beginning of the iteration.
do
echo $var
var--
done

That's probably enough for now. :)

  • Back
  • Forward

New articles:

  • Network discovery does not turn on in Windows 7/8/2008/2012
  • Error: This application failed to start because it could not find or load the Qt platform plugin "windows".
  • Configuring automatic restart of rphost.exe worker processes on 1C 8.3 server
  • How to reduce the size of the transaction log (.ldf) in MS SQL 2008/20012

    MS SQL, like any decent industrial DBMS, along with the database, keeps transaction logs that allow you to roll back the state...

0 Meeran Bala-Kumaran

I'm really trying to understand why this while loop never ends, when the loop starts my LOC variable is set to Testing/ which is the directory I created to test this program has the following layout:

I want the loop to end once all Directories have had the "count" function applied.
Here's what I tried;

I checked the count function and it doesn't create an infinite loop

I tried to run the algorithm manually

PARSE=1 LOC=$LOC/ count AVAILABLEDIR=$(ls $LOC -AFl | sed "1 d" | grep "/$" | awk "( print $9 )") while [ $PARSE = "1" ] do if [[ $(AVAILABLEDIR[@]) == "" ]]; then PARSE=0 fi DIRBASE=$LOC for a in $(AVAILABLEDIR[@]); do LOC="$(DIRBASE)$(a)" LOCLIST="$LOCLIST $LOC" count done for a in $(LOCLIST[@]); do TMPAVAILABLEDIR=$(ls $a -AFl | sed "1 d" | grep "/$" | awk "( print $9 )") PREPEND=$a if [[ $(TMPAVAILABLEDIR[@]) == "" ] ]; then continue fi for a in $(TMPAVAILABLEDIR[@]); do TMPAVAILABLEDIR2="$TMPAVAILABLEDIR2 $(PREPEND[@])$(a)" done NEWAVAILABLEDIR="$NEWAVAILABLEDIR $TMPAVAILABLEDIR2" done AVAILABLEDIR=$NEWAVAILABLEDIR NEWAVAILABLEDIR="" LOC="" done

I'm really struggling and any input would be greatly appreciated, I've been trying to figure this out for the last two hours.

bash infinite-loop

4 answers

You should try running the script with the -x argument or writing it on the first line:

#!/bin/bash -x

Then he tells you everything he does.

In this case, you may notice two errors:

    You never reload TMPAVAILABLEDIR2

    You also do ls on regular files.

If you really must avoid recursion, try this, completely without recursion:

#!/bin/bash count() ( echo counting "$1" ) todo=(Testing) while test $(#todo[@]) != 0 do doit=("$(todo[@])") todo= () for dir in "$(doit[@])" do for entry in "$dir"/* # if dir is empty, this shows an entry named "*" do test -e "$entry" || continue # skip the entry "*" of an empty dir count "$entry" test -d "$entry" || continue todo+=("$entry") done done done

However, please tell me why you can't use recursion? Is this some kind of allergy? Vow? Are there any local laws against recursive software where you live?

You wrote that you want to perform a "count" on all cuts. Check out the search options:

Find $LOC -type d | while read dir; do cd $LOC cd $(dir) count done

or shorter (when your function counter takes directory as parameter 1)

Find $LOC -type d | xargs count

Now I see that you don't want to use find or ls -R (recursive function). Then you should make your own recursive function like

Function parseDir ( ls -d */ $1 | while read dir; do count parseDir $1/$dir done )

I have no idea if this will work, but its an interesting question that I couldn't stop thinking about. Good luck

While true ; do for word in "$(echo *)" ; do if [[ -d "$word" ]] ; then d[$((i++))]="$PWD"/"$word" elif [[ -f "$word" ]] ;then f[$((j++))]="$PWD"/"$ word" fi done [[ $k -gt $i ]] && cd .. cd "$d[$((k++))]" || break done