Embedded Commands   «Prev  Next»
Lesson 5 Using embedded execution in a for loop
Objective Embed a command within a for loop.

Using Embedded Execution in a Unix for loop

Embedded execution is commonly used in conjunction with the for loop to cycle through the output of a command or to cycle through the lines of a file. Place the embedded command in place of the list of values used by the for loop. Assume you have a file called firstname:

$ cat firstname
Harry
Fred
Sally

To cycle through the contents of this file, use an embedded cat command in a for loop:

$ for name in `cat firstname`
> do
> echo $name is your name
> done
Harry is your name
Fred is your name
Sally is your name

Combine a for loop with embedded execution in Unix

In Unix-like systems, you can combine a for loop with embedded execution (command substitution) to perform various tasks. Here is an example that demonstrates this concept: Suppose you have a list of files in a directory, and you want to print the number of lines in each file.
  1. Using the $(command) syntax:
    for file in $(ls); do
        echo "Number of lines in $file: $(wc -l < "$file")"
    done
    
  2. Using backticks (command) syntax:
    for file in `ls`; do
        echo "Number of lines in $file: `wc -l < "$file"`"
    done
    

    In both examples, the embedded execution (command substitution) is used to get the list of files in the current directory using either $(ls) or ls. The for loop iterates over each file, and another command substitution is used within the loop to count the number of lines in the file using either
    $(wc -l < "$file")
    
    or
    wc -l < "$file". 
    

    The echo command then prints the file name and the number of lines in each file.
    Please note that using ls in command substitution is not recommended in practice, as it may not handle files with spaces or special characters correctly. A better approach is to use a shell glob pattern[1]:
    for file in *; do
        echo "Number of lines in $file: $(wc -l < "$file")"
    done
    

    This example uses a shell glob pattern (*) to iterate over the files in the current directory, avoiding the issues with ls in command substitution.

The shell will cat out the contents of the firstname file and use this as the set of values copied to the name variable.

Carriage returns

When embedded execution output is a list of values used in a for loop, the shell divides this output by spaces and by carriage returns. Sometimes, you will want to divide the output by carriage return only. By changing the value of the environment variable IFS, you can change this behavior of the for loop. The for loop uses the value of IFS to divide the command output that it uses as values. IFS defaults to spaces, tabs, and carriage returns. Change this value to carriage returns only by setting IFS to the value control-M. This represents a carriage return.
Let's look at a Insert Carriage Return illustrating this. Here's an example where each line is used as one value:

$ IFS=^M
$ for name in 'cat fullnames'
> do
>  echo $name is your name
> done
Harry Smith
Fred Brown
Sally Green
Doris Jones
Martha Jackson is your name

[1] shell glob pattern: A "shell glob pattern" is a pattern used by Unix-like shells to match and select files or directories based on wildcard characters.