-
-
Save takuzoo3868/65b0940747175301854000ce7e0b96b7 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash | |
# treeを擬似的に再現したスクリプト | |
dir_count=0 | |
file_count=0 | |
traverse() { | |
dir_count=$(expr $dir_count + 1) | |
local directory=$1 | |
local prefix=$2 | |
local children=($(ls $directory)) | |
local child_count=${#children[@]} | |
for idx in "${!children[@]}"; do | |
local child="${children[$idx]}" | |
local child_prefix="│ " | |
local pointer="├── " | |
if [ $idx -eq $(expr ${#children[@]} - 1) ]; then | |
pointer="└── " | |
child_prefix=" " | |
fi | |
echo "${prefix}${pointer}$child" | |
[ -d "$directory/$child" ] && | |
traverse "$directory/$child" "${prefix}$child_prefix" || | |
file_count=$(expr $file_count + 1) | |
done | |
} | |
root="." | |
[ "$#" -ne 0 ] && root="$1" | |
echo $root | |
traverse $root "" | |
echo | |
echo "$(expr $dir_count - 1) directories, $file_count files" |
You should replace
expr will launch a new process, while $(( )) is a bash internal.
For the same reason, and to handle filenames with spaces, you should replace ($(ls $directory)) with ("$directory"/*). Then you'll have to cut out the directory name.
Here is the result :
#!/usr/bin/env bash
dir_count=0
file_count=0
traverse() {
dir_count=$((dir_count + 1))
local directory=$1
local prefix=$2
local children=("$directory"/*)
local child_count=${#children[@]}
for idx in "${!children[@]}"
do local child="${children[$idx]}"
child=${child##*/}
local child_prefix="│ "
local pointer="├── "
if [ $idx -eq $(( ${#children[@]} - 1)) ]; then
pointer="└── "
child_prefix=" "
fi
echo "${prefix}${pointer}$child"
[ -d "$directory/$child" ] &&
traverse "$directory/$child" "$prefix$child_prefix" ||
file_count=$((file_count + 1))
done
}
root="."
[ "$#" -ne 0 ] && root="$1"
echo $root
traverse $root ""
echo
echo "$((dir_count - 1)) directories, $file_count files"
The output doesn't handle singular and plural cases as the actual tree command does.
You should replace (expr...)with(( ... )). expr will launch a new process, while $(( )) is a bash internal.
For the same reason, and to handle filenames with spaces, you should replace ($(ls $directory)) with ("$directory"/*). Then you'll have to cut out the directory name.
Here is the result :
...
Thanks a lot, @Vouze! Just updated this script to show trailing backslash for folders, not to print strange tail if the directory is empty, and colored folders and executable files in the tree:
#!/usr/bin/env bash
dir_count=0
file_count=0
traverse() {
dir_count=$((dir_count + 1))
local directory=$1
local prefix=$2
local children=("$directory"/*)
local child_count=${#children[@]}
for idx in "${!children[@]}"
do local child="${children[$idx]}"
child=${child##*/}
local child_prefix="│ "
local pointer="├── "
if [ $idx -eq $(( ${#children[@]} - 1)) ]; then
pointer="└── "
child_prefix=" "
fi
if [ -e $directory/$child ]; then
if [ -d "$directory/$child" ]; then
echo -e "${prefix}${pointer}\033[1;34m$child/\033[0m"
traverse "$directory/$child" "$prefix$child_prefix"
else
if [ -x $directory/$child ]; then
echo -e "${prefix}${pointer}\033[0;32m$child\033[0m"
else
echo "${prefix}${pointer}$child"
fi
file_count=$((file_count + 1))
fi
fi
done
}
root="."
[ "$#" -ne 0 ] && root="$1"
echo $root
traverse $root ""
echo
echo "$((dir_count - 1)) directories, $file_count files"
since i was too lazy to install tree, thank you very much