第 12.1 节 常用工具
版本:https://github.com/freebsd/freebsd-src/commit/cb991a228179639cc0568fdd5d4b4b07b6f47b5a
常用脚本(列出目录及文件)
import os
import argparse
def print_tree(root_dir, indent="", level=None, current_level=0):
if level is not None and current_level >= level:
return
items = sorted(os.listdir(root_dir)) # 确保顺序一致
for index, item in enumerate(items):
path = os.path.join(root_dir, item)
is_last = index == len(items) - 1
prefix = "└── " if is_last else "├── "
print(indent + prefix + item)
if os.path.isdir(path):
new_indent = indent + (" " if is_last else "│ ")
print_tree(path, new_indent, level, current_level + 1)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="打印目录树。")
parser.add_argument("directory", type=str, help="要打印的目录路径")
parser.add_argument("-l", "--level", type=int, default=None, help="打印的最大层级,默认不限制")
args = parser.parse_args()
if os.path.isdir(args.directory):
print(args.directory)
print_tree(args.directory, level=args.level)
else:
print("无效的目录路径。")
C 语言版本:
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
void print_tree(const char *root_dir, const char *indent, int level, int current_level) {
if (level != -1 && current_level >= level) {
return;
}
DIR *dir = opendir(root_dir);
if (!dir) {
perror("opendir");
return;
}
struct dirent *entry;
struct stat statbuf;
int count = 0;
// 统计文件和目录的数量
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
count++;
}
rewinddir(dir);
int index = 0;
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
char path[1024];
snprintf(path, sizeof(path), "%s/%s", root_dir, entry->d_name);
stat(path, &statbuf);
int is_last = (index == count - 1);
printf("%s%s── %s\n", indent, is_last ? "└" : "├", entry->d_name);
if (S_ISDIR(statbuf.st_mode)) {
char new_indent[1024];
snprintf(new_indent, sizeof(new_indent), "%s%s ", indent, is_last ? " " : "│");
print_tree(path, new_indent, level, current_level + 1);
}
index++;
}
closedir(dir);
}
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "用法: %s <目录路径> [-l 层级]\n", argv[0]);
return 1;
}
int level = -1; // -1 代表不限制层级
if (argc == 4 && strcmp(argv[2], "-l") == 0) {
level = atoi(argv[3]);
}
struct stat statbuf;
if (stat(argv[1], &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) {
fprintf(stderr, "无效的目录路径。\n");
return 1;
}
printf("%s\n", argv[1]);
print_tree(argv[1], "", level, 0);
return 0;
}
常用脚本(仅列出目录)
import os
import argparse
def print_tree(root_dir, indent="", level=None, current_level=0):
if level is not None and current_level >= level:
return
items = sorted([item for item in os.listdir(root_dir) if os.path.isdir(os.path.join(root_dir, item))]) # 只列出文件夹
for index, item in enumerate(items):
path = os.path.join(root_dir, item)
is_last = index == len(items) - 1
prefix = "└── " if is_last else "├── "
print(indent + prefix + item)
new_indent = indent + (" " if is_last else "│ ")
print_tree(path, new_indent, level, current_level + 1)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="打印目录树,仅包含文件夹。")
parser.add_argument("directory", type=str, help="要打印的目录路径")
parser.add_argument("-l", "--level", type=int, default=None, help="打印的最大层级,默认不限制")
args = parser.parse_args()
if os.path.isdir(args.directory):
print(args.directory)
print_tree(args.directory, level=args.level)
else:
print("无效的目录路径。")
用法:python script.py /path/to/directory -l 2
若不提供(或者提供更高的数值)参数 -l
,则会继续递归打印更深层的目录结构。
示例 1:
PS C:\Users\ykla> python C:\Users\ykla\Desktop\1.py C:\Users\ykla\Desktop\freebsd-src-main >> C:\Users\ykla\Desktop\1.txt
将会生成所有层级的目录和文件树状图。
示例 2
PS C:\Users\ykla> python C:\Users\ykla\Desktop\1.py C:\Users\ykla\Desktop\freebsd-src-main -l 1
将会打印根路径下所有目录和文件树状图。
C 语言版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
void print_tree(const char *root_dir, const char *indent, int level, int current_level) {
if (level != -1 && current_level >= level) {
return;
}
DIR *dir = opendir(root_dir);
if (!dir) {
perror("无法打开目录");
return;
}
struct dirent *entry;
struct stat statbuf;
char full_path[1024];
// 统计目录项数量
int count = 0;
while ((entry = readdir(dir)) != NULL) {
snprintf(full_path, sizeof(full_path), "%s/%s", root_dir, entry->d_name);
if (stat(full_path, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
count++;
}
}
}
rewinddir(dir);
// 打印目录树
int index = 0;
while ((entry = readdir(dir)) != NULL) {
snprintf(full_path, sizeof(full_path), "%s/%s", root_dir, entry->d_name);
if (stat(full_path, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
int is_last = (++index == count);
printf("%s%s%s\n", indent, is_last ? "└── " : "├── ", entry->d_name);
char new_indent[1024];
snprintf(new_indent, sizeof(new_indent), "%s%s", indent, is_last ? " " : "│ ");
print_tree(full_path, new_indent, level, current_level + 1);
}
}
}
closedir(dir);
}
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("用法: %s <目录路径> [-l <层级限制>]\n", argv[0]);
return 1;
}
int level = -1; // 默认无限制
if (argc == 4 && strcmp(argv[2], "-l") == 0) {
level = atoi(argv[3]);
}
struct stat statbuf;
if (stat(argv[1], &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) {
printf("无效的目录路径。\n");
return 1;
}
printf("%s\n", argv[1]);
print_tree(argv[1], "", level, 0);
return 0;
}
递归打印指定目录及其文件文件夹,排除指定文件和文件夹
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
int should_filter(const char *filename) {
const char *extensions[] = {
".h", ".so", ".mps", ".gz", ".ko", ".0", ".646", ".esdb", ".mk", ".kbd",
".pem", ".m4", ".fnt", ".kbd",".txt",".html",".gif",".c", ".cat", ".a", ".debug", NULL
};
for (int i = 0; extensions[i] != NULL; i++) {
size_t len = strlen(extensions[i]);
size_t filename_len = strlen(filename);
if (filename_len > len && strcmp(filename + filename_len - len, extensions[i]) == 0) {
return 1;
}
}
return 0;
}
int should_skip_directory(const char *dirname) {
// 检查文件夹名称中是否包含 "UTF-8" 或 "ISO8859-1"
if (strstr(dirname, "UTF-8") != NULL || strstr(dirname, "ISO8859-1") != NULL) {
return 1; // 符合条件,跳过子文件夹
}
return 0;
}
void print_tree(const char *root_dir, const char *indent, int level, int current_level) {
if (level != -1 && current_level >= level) {
return;
}
DIR *dir = opendir(root_dir);
if (!dir) {
perror("opendir");
return;
}
struct dirent *entry;
struct stat statbuf;
int count = 0;
int filtered_count = 0; // 统计符合过滤条件的文件数量
// 统计文件和目录的数量
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
if (should_filter(entry->d_name)) {
filtered_count++;
} else {
count++;
}
}
rewinddir(dir);
int index = 0;
int filtered_displayed = 0; // 标记是否已经显示过一次 "……"
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
char path[1024];
snprintf(path, sizeof(path), "%s/%s", root_dir, entry->d_name);
stat(path, &statbuf);
int is_last = (index == count + filtered_count - 1);
const char *filename = entry->d_name;
// 检查文件夹名称是否包含 "UTF-8" 或 "ISO8859-1"
if (should_skip_directory(filename)) {
if (!filtered_displayed) {
printf("%s%s── ……\n", indent, is_last ? "└" : "├");
filtered_displayed = 1; // 已经显示过一次 "……"
}
} else {
if (should_filter(filename)) {
if (!filtered_displayed) {
printf("%s%s── ……\n", indent, is_last ? "└" : "├");
filtered_displayed = 1; // 已经显示过一次 "……"
}
} else {
printf("%s%s── %s\n", indent, is_last ? "└" : "├", filename);
if (S_ISDIR(statbuf.st_mode)) {
char new_indent[1024];
snprintf(new_indent, sizeof(new_indent), "%s%s ", indent, is_last ? " " : "│");
print_tree(path, new_indent, level, current_level + 1);
}
}
}
index++;
}
closedir(dir);
}
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "用法: %s <目录路径> [-l 层级]\n", argv[0]);
return 1;
}
int level = -1; // -1 代表不限制层级
if (argc == 4 && strcmp(argv[2], "-l") == 0) {
level = atoi(argv[3]);
}
struct stat statbuf;
if (stat(argv[1], &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) {
fprintf(stderr, "无效的目录路径。\n");
return 1;
}
printf("%s\n", argv[1]);
print_tree(argv[1], "", level, 0);
return 0;
}
最后更新于