Created
May 29, 2024 10:11
-
-
Save hunandy14/dbdd7f5114a50b74c825772ba3125514 to your computer and use it in GitHub Desktop.
This script shows the directory tree, color-codes files and folders, and optionally displays file sizes and hidden files.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# This script displays the directory tree structure, color-codes files and folders, | |
# and optionally shows file sizes and hidden files. | |
# Usage: | |
# tree.sh [-a] [-s] <directory> | |
# -a Show all files including hidden files | |
# -s Show file sizes | |
# Detailed Usage: | |
# - `-a` or `--all`: Show all files, including hidden files. | |
# - `-s` or `--size`: Display the size of each file. | |
# Examples: | |
# 1. Show the directory structure, including hidden files and file sizes: | |
# tree.sh -a -s testdir/ | |
# | |
# 2. Show the directory structure without hidden files and file sizes: | |
# tree.sh testdir/ | |
# | |
# 3. Show the directory structure with file sizes but without hidden files: | |
# tree.sh -s testdir/ | |
# Function to format file size | |
function format_size() { | |
local size=$1 | |
local units=("B" "KB" "MB" "GB" "TB" "PB") | |
local unit_index=0 | |
local decimal_places=3 | |
while (( $(echo "$size >= 1024" | bc -l) )); do | |
size=$(echo "scale=$decimal_places; $size / 1024" | bc) | |
unit_index=$(( unit_index + 1 )) | |
done | |
size=$(echo $size | awk '{printf "%.'$decimal_places'f", $0}') | |
size=$(echo $size | sed 's/\.0*$//;s/\.\([0-9]*[1-9]\)0*$/.\1/') | |
echo "$size ${units[$unit_index]}" | |
} | |
# Function to print the item name with color based on file type | |
function print_item() { | |
local item_name=$1 | |
shift | |
local description="" | |
local item_type="" | |
while [ $# -gt 0 ]; do | |
case $1 in | |
--description=*|-d) | |
if [[ "$1" == "--description="* ]]; then | |
description="${1#*=}" | |
shift | |
else | |
description="$2" | |
shift 2 | |
fi | |
;; | |
--type=*|-t) | |
if [[ "$1" == "--type="* ]]; then | |
item_type="${1#*=}" | |
shift | |
else | |
item_type="$2" | |
shift 2 | |
fi | |
;; | |
*) | |
echo "Unknown argument: $1" | |
return 1 | |
;; | |
esac | |
done | |
local base_name=$(basename "$item_name") | |
local extension="${base_name##*.}" | |
local COLOR_RESET="\033[0m" | |
local COLOR_FOLDER="\033[1;34m" # Blue color for folders | |
local COLOR_EXEC="\033[1;32m" # Green color for executable files | |
local COLOR_LINK="\033[1;36m" # Cyan color for links | |
local COLOR_COMPRESSED="\033[1;31m" # Red color for compressed files | |
local COLOR_IMAGE="\033[1;35m" # Magenta color for image files | |
local COLOR_VIDEO="\033[1;33m" # Yellow color for video files | |
local COLOR_AUDIO="\033[1;36m" # Cyan color for audio files | |
local COLOR_FIFO="\033[1;33;40m" # Yellow background black text for FIFO | |
local COLOR_DEVICE="\033[1;34;43m" # Yellow background blue text for devices | |
local COLOR_SUID="\033[1;37;41m" # White background red text for SUID files | |
local COLOR_SGID="\033[1;30;43m" # Black background yellow text for SGID files | |
local COLOR_STICKY="\033[1;37;44m" # Blue background white text for sticky directories | |
local COLOR_OW="\033[1;30;42m" # Green background black text for other-writable directories | |
local COLOR_DEFAULT="\033[0m" # Default color for other files | |
local colored_name | |
if [ "$item_type" = "folder" ]; then | |
colored_name="${COLOR_FOLDER}${base_name}/${COLOR_RESET}" | |
else | |
if [ -x "$item_name" ]; then | |
colored_name="${COLOR_EXEC}${base_name}${COLOR_RESET}" | |
elif [ -L "$item_name" ]; then | |
colored_name="${COLOR_LINK}${base_name}${COLOR_RESET}" | |
elif [[ "$extension" =~ ^(zip|tar|gz|bz2|xz|7z|rar)$ ]]; then | |
colored_name="${COLOR_COMPRESSED}${base_name}${COLOR_RESET}" | |
elif [[ "$extension" =~ ^(jpg|jpeg|png|gif|bmp|tiff|svg|ico)$ ]]; then | |
colored_name="${COLOR_IMAGE}${base_name}${COLOR_RESET}" | |
elif [[ "$extension" =~ ^(mp4|mkv|avi|mov|flv|wmv|webm)$ ]]; then | |
colored_name="${COLOR_VIDEO}${base_name}${COLOR_RESET}" | |
elif [[ "$extension" =~ ^(mp3|wav|ogg|flac|aac|m4a)$ ]]; then | |
colored_name="${COLOR_AUDIO}${base_name}${COLOR_RESET}" | |
elif [ -p "$item_name" ]; then | |
colored_name="${COLOR_FIFO}${base_name}${COLOR_RESET}" | |
elif [ -b "$item_name" ] || [ -c "$item_name" ]; then | |
colored_name="${COLOR_DEVICE}${base_name}${COLOR_RESET}" | |
elif [ -u "$item_name" ]; then | |
colored_name="${COLOR_SUID}${base_name}${COLOR_RESET}" | |
elif [ -g "$item_name" ]; then | |
colored_name="${COLOR_SGID}${base_name}${COLOR_RESET}" | |
elif [ -k "$item_name" ]; then | |
colored_name="${COLOR_STICKY}${base_name}${COLOR_RESET}" | |
elif [ -w "$item_name" ] && [ -d "$item_name" ]; then | |
colored_name="${COLOR_OW}${base_name}${COLOR_RESET}" | |
else | |
colored_name="${COLOR_DEFAULT}${base_name}${COLOR_RESET}" | |
fi | |
fi | |
if [ -n "$description" ]; then | |
echo -e "${colored_name} ${description}" | |
else | |
echo -e "${colored_name}" | |
fi | |
} | |
# Function to recursively print the directory tree structure | |
function print_tree() { | |
local directory=$1 | |
local prefix=$2 | |
local files=() | |
if $show_hidden; then | |
files=("$directory"/{.,}*) | |
else | |
files=("$directory"/*) | |
fi | |
# Filter out non-existent files and directories (handle empty directories) | |
files=(${files[@]/*\*/}) | |
local last_index=$((${#files[@]} - 1)) | |
for i in "${!files[@]}"; do | |
local file="${files[$i]}" | |
local basename=$(basename "$file") | |
local new_prefix="$prefix" | |
if [ "$basename" == "." ] || [ "$basename" == ".." ]; then | |
continue | |
fi | |
if [ $i -eq $last_index ]; then | |
echo -n "${prefix}└── " | |
new_prefix="$prefix " | |
else | |
echo -n "${prefix}├── " | |
new_prefix="$prefix│ " | |
fi | |
if [ -d "$file" ]; then | |
dir_count=$((dir_count + 1)) | |
print_item "$file" -t "folder" | |
print_tree "$file" "$new_prefix" | |
else | |
if $show_size; then | |
local size=$(stat -c %s "$file") | |
local formatted_size=$(format_size $size) | |
print_item "$file" -d "($formatted_size)" -t "file" | |
else | |
print_item "$file" -t "file" | |
fi | |
file_count=$((file_count + 1)) | |
fi | |
done | |
} | |
# Default options | |
show_hidden=false | |
show_size=false | |
dir_count=0 | |
file_count=0 | |
# Parse options | |
while getopts "as" opt; do | |
case $opt in | |
a) | |
show_hidden=true | |
;; | |
s) | |
show_size=true | |
;; | |
*) | |
echo "Usage: $0 [-a] [-s] <directory>" | |
echo " -a Show all files including hidden files" | |
echo " -s Show file sizes" | |
exit 1 | |
;; | |
esac | |
done | |
shift $((OPTIND - 1)) | |
# Check if a directory is provided as an argument | |
if [ -z "$1" ]; then | |
echo "Usage: $0 [-a] [-s] <directory>" | |
echo " -a Show all files including hidden files" | |
echo " -s Show file sizes" | |
exit 1 | |
fi | |
# Remove trailing slash from the directory if it exists | |
directory=$(echo "$1" | sed 's:/*$::') | |
# Print the initial directory with color | |
print_item "$directory" -t "folder" | |
print_tree "$directory" "" | |
# Print the summary | |
echo -e "\n$dir_count directories, $file_count files" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment