2024年5月29日 星期三

Linux 中仿 tree 輸出的 Shell 檔案

Linux 中仿 tree 輸出的 Shell 檔案

2024-05-29 一個比較完整的檔案寫完了放在gist上 Tree.sh (github.com)




某些環境基於某些原因實在是沒辦法,只能自己自幹一個這邊給一個 GPT 的作品,最基本基本的功能是有了


tree.sh

#!/bin/bash

# Function to print the folder name with color
function print_folder() {
    local folder_name=$1
    local COLOR_RESET="\033[0m"
    local COLOR_FOLDER="\033[1;34m" # Blue color for folders
    echo -e "${COLOR_FOLDER}${folder_name}/${COLOR_RESET}"
}

# Function to recursively print the directory tree structure
function print_tree() {
    local directory=$1
    local prefix=$2
    local files=("$directory"/*)
    local last_index=$((${#files[@]} - 1))

    # Check if the directory is empty
    if [ "$files" = "$directory/*" ]; then
        return
    fi

    for i in "${!files[@]}"; do
        local file="${files[$i]}"
        local basename=$(basename "$file")
        local new_prefix="$prefix"

        if [ $i -eq $last_index ]; then
            echo -n "${prefix}└── "
            new_prefix="$prefix    "
        else
            echo -n "${prefix}├── "
            new_prefix="$prefix│   "
        fi

        if [ -d "$file" ]; then
            print_folder "$basename"
            print_tree "$file" "$new_prefix"
        else
            echo "$basename"
        fi
    done
}

# Check if a directory is provided as an argument
if [ -z "$1" ]; then
    echo "Usage: $0 <directory>"
    exit 1
fi

# Remove trailing slash from the directory if it exists
directory=$(echo "$1" | sed 's:/*$::')

# Print the initial directory with color
print_folder "$(basename "$directory")"
print_tree "$directory" ""


使用的話跟 tree 差不多沒兩樣先給執行權限

chmod +x tree.sh

然後使用

./tree.sh testdir


輸出結果

testdir/
├── file1.txt
├── file2.txt
├── subdir1/
│   ├── file2.txt
│   ├── file3.txt
│   ├── subsubdir1/
│   │   └── file4.txt
│   └── subsubdir2/
│       └── file5.txt
└── subdir2/
    ├── file3.txt
    ├── file6.txt
    └── subsubdir1/
        └── file7.txt




精簡高壓版本

邏輯一樣的只是完全不管可讀性,能壓能壓版本

tree(){
    [ -z "$1" ] && { echo "Usage: $0 <directory>"; exit 1; }
    print_folder() { echo -e "\\033[1;34m${1}/\\033[0m"; }
    print_tree() { local dir=$1 prefix=$2; local files=("$dir"/*)
        print_tree_core() { [ $1 -ge ${#files[@]} ] && return
            local idx=$1; local file="${files[$idx]}"
            local base=$(basename "$file") new_prefix="$prefix"
            ([ $idx -eq $((${#files[@]} - 1)) ]) && {
                echo -n "${prefix}└── "; new_prefix="$prefix    "
            } || { echo -n "${prefix}├── "; new_prefix="$prefix│   "
            }; ([ -d "$file" ] && {
                print_folder "$base"; print_tree "$file" "$new_prefix"
            } || echo "$base"); print_tree_core $(($idx + 1))
        }; [ "$files" = "$dir/*" ] && return || print_tree_core 0
    }; dir=$(echo "$1" | sed 's:/*$::')
    print_folder "$(basename "$dir")"; print_tree "$dir" ""
}

貼上之後直接呼叫 tree 就可以用了 (要是原本就有會被覆蓋功能,被蓋了重啟終端就好)

tree testdir



增加顯示有多少個檔案

tree(){
    [ -z "$1" ] && { echo "Usage: $0 <directory>"; exit 1; }
    print_folder() { echo -e "\\033[1;34m${1}/\\033[0m"; }
    print_tree() { local dir=$1 prefix=$2; local files=("$dir"/*)
        print_tree_core() { [ $1 -ge ${#files[@]} ] && return
            local idx=$1; local file="${files[$idx]}"
            local base=$(basename "$file") new_prefix="$prefix"
            ([ $idx -eq $((${#files[@]} - 1)) ]) && {
                echo -n "${prefix}└── "; new_prefix="$prefix    "
            } || { echo -n "${prefix}├── "; new_prefix="$prefix│   "
            }; [ -d "$file" ] && { dir_cnt=$((dir_cnt + 1))
                print_folder "$base"; print_tree "$file" "$new_prefix"
            } || { echo "$base"; file_cnt=$((file_cnt + 1))
            }; print_tree_core $(($idx + 1))
        }; [ "$files" = "$dir/*" ] && return || print_tree_core 0
    }; dir=$(echo "$1" | sed 's:/*$::')
    print_folder "$(basename "$dir")"; dir_cnt=0; file_cnt=0
    print_tree "$dir"; echo -e "\n$dir_cnt directories, $file_cnt files"
}


增加顯示隱藏檔案

tree(){
    [ -z "$1" ] && { echo "Usage: $0 <directory>"; exit 1; }
    print_folder() { echo -e "\\033[1;34m${1}/\\033[0m"; }
    print_tree() { local dir=$1 prefix=$2; local files
        files=("${dir}"/.* "${dir}"/*); files=(${files[@]/*\*/})
        print_tree_core() { [ $1 -ge ${#files[@]} ] && return
            local idx=$1; local file="${files[$idx]}"
            local base=$(basename "$file") new_prefix="$prefix"
            ([ "$base" == "." ] || [ "$base" == ".." ]) && {
                print_tree_core $(($idx + 1)); return
            }; ([ $idx -eq $((${#files[@]} - 1)) ]) && {
                echo -n "${prefix}└── "; new_prefix="$prefix    "
            } || { echo -n "${prefix}├── "; new_prefix="$prefix│   "
            }; [ -d "$file" ] && { dir_cnt=$((dir_cnt + 1))
                print_folder "$base"; print_tree "$file" "$new_prefix"
            } || { echo "$base"; file_cnt=$((file_cnt + 1))
            }; print_tree_core $(($idx + 1))
        }; [ ${#files[@]} -eq 0 ] && return || print_tree_core 0
    }; dir=$(echo "$1" | sed 's:/*$::')
    print_folder "$(basename "$dir")"; dir_cnt=0; file_cnt=0
    print_tree "$dir"; echo -e "\n$dir_cnt directories, $file_cnt files"
}





魔法咒語

最後是魔法咒語,特地用函式包起來是要把路徑後置到後面,方便貼上直接些改
_(){ d=$(realpath "$1"); echo "$d"; find "$1" | sort | sed '1d;s|^'"$1"'| |;s/\/\([^/]*\)$/|-- \1/;s/\/[^/|]*/|   /g'; };_ .

為什麼要用醜醜的 |-- 而不是更漂亮的 └── 是因為,用 Ascii 以外的符號很容易就噴亂碼,自己根據情況斟酌使用吧




沒有留言:

張貼留言