Home > Software design >  Bash recursive function using while loop
Bash recursive function using while loop

Time:06-08

I have a function called func1. When passed an argument it will generate a list of items. I need each of these items to be passed as argument to func1 and so on until there is no more to pass. Ex.

func1 <arg>  | while read item
do
   func1 item | while read item1
   do
     func1 item1 <--- how to do this recursion?
   done
done

Just need some implementation ideas. Thank you

CodePudding user response:

Try this somewhat contrived Shellcheck-clean demonstration program:

#! /bin/bash -p

shopt -s dotglob nullglob

# Print the paths to the tree of directories rooted at the given directory
function dirtree
{
    local -r dir=$1

    printf '%s\n' "$dir"
    local entry subdir
    for entry in "$dir"/*; do
        [[ -L $entry ]] && continue
        [[ -d $entry ]] && printf '%s\0' "$entry"
    done \
        |   while IFS= read -r -d '' subdir; do
                dirtree "$subdir"
            done

    return 0
}

dirtree ~
  • shopt -s sets some Bash configurations:
    • dotglob enables globs to match files and directories that begin with ..
    • nullglob makes globs expand to nothing when nothing matches (otherwise they expand to the glob pattern itself, which is almost never useful in programs).
  • There's no explicit handling of base cases because when descending a directory structure you are guaranteed to eventually reach a directory that has no subdirectories. Symlinks can cause cycle in directory structures, so the [[ -L $entry ]] && continue line is in the code to stop symlinks being followed.

The function is contrived because the while loop and pipeline are unnecessary. A cleaner, simpler, and more efficient alternative is:

# Print the paths to the tree of directories rooted at the given directory
function dirtree2
{
    local -r dir=$1

    printf '%s\n' "$dir"
    local entry
    for entry in "$dir"/*; do
        [[ -L $entry ]] && continue
        [[ -d $entry ]] && dirtree2 "$entry"
    done

    return 0
}
  • Related