[!前言]
对于经常写笔记或者写文档得同学来说,经常会需要获取一个项目工程下得目录结构,那么如何在不需要下载或者安装插件来达到这个目的呢?
示例
只含有三级目录
包含文件得四级文件树
指定忽略部分文件或者文件夹,比如target目录,logs目录
使用方法
新建脚本
在你需要输出目录结构得文件夹下新建.sh脚本,名称随意,比如叫tree.sh
输入脚本代码
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180#!/bin/bash# 获取当前脚本的名称script_name=$(basename "$0")output_file="tree_output.txt"# 定义读取 .gitignore 文件的函数read_gitignore() { local directory="$1" gitignore_file="$directory/.gitignore" if [[ -f "$gitignore_file" ]]; then # 读取 .gitignore 文件并排除注释和空行 GITIGNORE_RULES=($(grep -Ev '^\s*#|^\s*$' "$gitignore_file")) else GITIGNORE_RULES=() fi # 将脚本名称和输出文件添加到排除列表 GITIGNORE_RULES+=("$script_name" "$output_file")}# 检查文件或文件夹是否应该被忽略is_excluded() { local path="$1" local relative_path="${path#$directory/}" local match_exclude=0 # 是否匹配到排除规则 local match_include=0 # 是否匹配到包含规则(例外) # 转换为相对路径,并确保路径不以斜杠开头 relative_path=$(echo "$relative_path" | sed 's/^\///') # 遍历 .gitignore 规则 for rule in "${GITIGNORE_RULES[@]}"; do local original_rule="$rule" local is_inclusion=0 # 默认为排除规则 if [[ "${rule:0:1}" == "!" ]]; then is_inclusion=1 # 如果是例外规则 rule="${rule:1}" # 移除开头的感叹号 fi # 替换通配符 * 和 ? local pattern="${rule//\*/.*}" pattern="${pattern//\?/.}" # 根据规则中的斜杠位置构建不同的正则表达式 if [[ "$rule" == /* ]]; then pattern="${pattern#/}" pattern="^$pattern($|/.*)$" elif [[ "$rule" == */ ]]; then pattern="${pattern%/}" pattern="^$pattern(/.*|$)" elif [[ "$rule" == */* ]]; then pattern="($|^.*/)$pattern($|/.*)$" else pattern="($|^.*/)$pattern($|/.*)$" fi # 检查路径匹配 if [[ "$relative_path" =~ $pattern ]]; then if [[ "$is_inclusion" -eq 1 ]]; then match_include=1 # 匹配到例外规则,标记为包含 else match_exclude=1 # 匹配到排除规则,标记为排除 fi fi done # 如果匹配到包含规则,返回0(不忽略) # 如果匹配到排除规则且没有匹配到包含规则,返回1(忽略) if [[ "$match_include" -eq 1 ]]; then return 0 elif [[ "$match_exclude" -eq 1 ]]; then return 1 else return 0 # 默认不忽略 fi}# 定义全局数组来记录每层级的计数declare -a count_stackdeclare -a index_stack# 定义递归函数来打印目录结构print_tree() { local directory="$1" local prefix="$2" local exclude_files="$3" local level="$4" local max_level="$5" # 递归到达最大层级时返回 if [[ -n "$max_level" && "$level" -gt "$max_level" ]]; then return fi # 获取当前目录下的所有文件和文件夹 shopt -s nullglob local items=("$directory"/*) shopt -u nullglob local count=${#items[@]} count_stack[$level]=$count index_stack[$level]=0 while [[ ${index_stack[$level]} -lt ${count_stack[$level]} ]]; do local item="${items[${index_stack[$level]}]}" local base_name=$(basename "$item") local is_last=$((index_stack[$level] == count - 1)) index_stack[$level]=$((index_stack[$level] + 1)) # 跳过应该被 .gitignore 排除的文件夹和文件 if [[ "$apply_gitignore" == "y" ]]; then is_excluded "$item" if [[ $? -eq 1 ]]; then # 检查 is_excluded 的返回值,如果为 1 则忽略 continue fi fi # 确定当前项的前缀符号 if [ "$is_last" == "1" ]; then current_prefix="${prefix}└── $base_name" new_prefix="${prefix} " else current_prefix="${prefix}├── $base_name" new_prefix="${prefix}│ " fi if [ -d "$item" ]; then # 打印目录名 echo "$current_prefix" # 保存目录名到输出变量 output_tree+="$current_prefix"$'\n' # 递归调用自己 print_tree "$item" "$new_prefix" "$exclude_files" $((level + 1)) "$max_level" elif [ "$exclude_files" != "y" ]; then # 打印文件名 echo "$current_prefix" # 保存文件名到输出变量 output_tree+="$current_prefix"$'\n' fi done}# 获取当前目录的树型结构directory="$(pwd)"# 询问用户是否应用 .gitignore 中的内容read -p "是否应用 .gitignore 中的内容? (y/n): " apply_gitignore# 如果选择不应用,则清空排除列表if [ "$apply_gitignore" == "n" ]; then GITIGNORE_RULES=()else # 读取 .gitignore 文件 read_gitignore "$directory"fi# 询问用户是否不包含文件read -p "输出的树是否不包含文件? (y/n): " exclude_files# 询问用户输出的层级read -p "请输入输出的层级 (默认输出所有层级): " max_level# 初始化输出变量output_tree=""# 打印并保存树型结构echo "$(basename "$directory")"output_tree+="$(basename "$directory")"$'\n'print_tree "$directory" "" "$exclude_files" 1 "$max_level"# 询问用户是否导出树型结构read -p "是否导出这个输出的树? (y/n): " export_treeif [ "$export_tree" == "y" ]; then echo -e "$output_tree" > "$output_file" echo "树型结构已导出到 $output_file"fi
双击运行
运行过程中会有需要交互得地方
是否应用 .gitignore 中的内容?
我们知道git提交会配置.gitignore来忽略不想提交得内容,spring boot中得target目录、logs目录等,前端得.vscode目录等,我们并不想将这些内容输出到文件树中,就在第一个用户交互得地方输入y。
输出的树是否不包含文件?
如果输入y则会将所有文件输出到结果得树中。
请输入输出的层级 (默认输出所有层级):
默认为所有层级,输入数字则输出数字对应得层级
是否导出这个输出的树? (y/n)
最后是导出这个树到txt文件中,便于复制使用