Ubuntu – Explaining a shell script to recursively print full directory tree

bashcommand linescripts

I found a script to recursively print a full directory tree, but I cannot understand it. Can anyone fully describe it? I have just started shell scripting. Here is the code:

#!/bin/bash
walk() {
        local indent="${2:-0}"
        printf "%*s%s\n" $indent '' "$1"
        for entry in "$1"/*; do
                [[ -d "$entry" ]] && walk "$entry" $((indent+4))
        done
}
walk "$1"

Best Answer

This script defines a function walk() and then runs walk on the first argument passed to the script.

The function first defines a local variable (one known only to the function and its children) indent

indent is locally defined as "${2:-0}". This means that if $2 (the second argument received by the walk command) is unset, then make it 0. This variable is local so that you cannot pass a second argument to the script yourself.

The function then prints the contents of the directory specified on the command line ($1) in this format

printf "%*s%s\n" $indent '' "$1"

This means, print $indent number of spaces, then print the name of the directory as a string (so a number is not expected), then print a newline.

Then the function runs a loop

for entry in $1/*; do

This assigns every non-hidden file or sub-directory in $1 (the directory specified as the first argument to walk) to the variable entry and loops over them, running this command on them:

[[ -d "$entry" ]] && walk "$entry" $((indent+4))

This means, if entry is a directory, then run walk on entry. Now walk has a second argument $((indent+4)), which will be used instead of 0 as the new value of indent. The effect of this is that the first level directory is not indented at all, but the second level directories are indented 4 spaces, the third level 8 spaces, etc. Since entry is now the first argument, $1 of the walk function, it will recurse throughout the structure.

The script ends by running the walk function on the positional parameter $1, the first argument passed to the script. Usage could be

./script directory

This means directory is $1and walk will be run on directory.

It would be nice if the script printed regular files I think, but they would look confusing without some elaborate formatting. I recommend using tree for this purpose instead of the script!

Related Question