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
}