Bash for

From NovaOrdis Knowledge Base
Revision as of 22:22, 18 May 2021 by Ovidiu (talk | contribs) (→‎Iterating over Lines in the Same bash Process)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

External

Internal

Overview

The for built-in command expand words, and execute commands once for each member in the resultant list, with i bound to the current member.

   for i in words; do commands; done

Alternatively, for:

   for i do commands; done

commands executes for each positional parameter (as if in "$@" had been specified.

Yes another alternative form:

    for (( i=0; i<${#names[@]}; i++ )); do
        local name=${names[${i}]}
        echo "${name}"
    done

Iterating through $1, $2, $3 ...

The Simple Version

     for i do
         echo ${i}
     done

Using the Argument Array

TODO

Iterating through a space separated list

    s="a b c"
    for i in ${s}
        do
            echo ${i}
        done

or

     s="a b c"
     for i in ${s}; do echo ${i}; done

Note the use of ";"

Iterating over Lines in the Same bash Process

IFS="$(printf '\n\r')"
for line in $(cat ./file.txt); do
   echo "${line}"
done
IFS="$(printf ' \t\n')"

Note 1 Be careful when setting IFS before a for loop, even if you restore the default value after the loop: everything inside the loop will use the non-standard IFS value and it may not work as expected.

For more details on IFS and possible pitfalls while using it, see IFS.


Note 2 This method does not work very well with large files. The content of the file will be first buffered in memory so the loop will appear irresponsive, at least for a while.

Iterating over a File List

Use a globbing expression after in and the shell will replace it with the list of files matching the expression:

for f in dir/B*; do
    echo ${f}
done

If file names match, the replacement closely matches the expression (example "dir/BMW.txt dir/Bentley.txt").

In case no filename match, the for body is executed with he literal expression ("dir/B*" in the example above).

Iterating over a ps Output

IFS="$(printf '\n\r')"
for proc_details in $(ps -ef | grep "..." | grep -v grep); do
    echo "${proc_details}"
done
IFS="$(printf ' \t\n')"