博主之前用的xmind,后来发现html做成APP似乎更好一些
以下是源码,据此还可以做出Python等

html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <title>Bash 内建命令树形结构</title><style>
/* 保持原有CSS 样式不变*/
:root {
--primary-color: #4f46e5;
--secondary-color: #7c3aed;
--accent-color: #8b5cf6;
--text-color: #1e293b;
--text-secondary: #64748b;
--bg-color: #f8fafc;
--border-color: #e2e8f0;
--hover-bg: #f1f5f9;
--code-bg: #ffffff;
--tree-line: #cbd5e1;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
font-size: 13px;
line-height: 1.5;
color: #334155;
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
}
.container {
flex: 1;
display: flex;
flex-direction: column;
background-color: rgba(255, 255, 255, 0.95);
overflow: hidden;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
}
header {
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
color: #fff;
padding: 12px 16px;
text-align: left;
border-bottom: 1px solid var(--border-color);
flex-shrink: 0;
z-index: 10;
}
header h1 {
font-size: 18px;
font-weight: 600;
margin-bottom: 4px;
}
header p {
opacity: 0.9;
font-size: 12px;
}
.controls {
padding: 10px 16px;
background-color: var(--code-bg);
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 8px;
flex-shrink: 0;
}
.controls button {
background: linear-gradient(135deg, var(--accent-color), var(--secondary-color));
color: white;
border: none;
padding: 6px 12px;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s;
font-size: 12px;
font-family: inherit;
}
.controls button:hover {
background: linear-gradient(135deg, var(--secondary-color), var(--primary-color));
transform: translateY(-1px);
}
#searchInput {
padding: 6px 10px;
border: 1px solid var(--border-color);
border-radius: 6px;
background-color: rgba(248, 250, 252, 0.8);
color: #334155;
font-size: 12px;
font-family: inherit;
width: 180px;
}
#searchInput:focus {
outline: none;
border-color: var(--accent-color);
box-shadow: 0 0 0 2px rgba(139, 92, 246, 0.2);
}
.tree-container {
flex: 1;
padding: 12px;
overflow: auto;
background-color: rgba(248, 250, 252, 0.5);
}
.tree ul {
list-style-type: none;
padding-left: 16px;
margin: 0;
}
.tree li {
position: relative;
padding: 1px 0;
white-space: nowrap;
}
.tree li::before {
content: "";
position: absolute;
left: -10px;
top: 8px;
width: 10px;
height: 1px;
background-color: var(--tree-line);
}
.tree li::after {
content: "";
position: absolute;
left: -10px;
top: -2px;
width: 1px;
height: 100%;
background-color: var(--tree-line);
}
.tree li:last-child::after {
height: 10px;
}
.tree > ul > li::before,
.tree > ul > li::after {
display: none;
}
.tree-node {
display: flex;
align-items: center;
cursor: pointer;
padding: 2px 4px;
border-radius: 4px;
transition: background-color 0.2s;
}
.tree-node:hover {
background-color: var(--hover-bg);
}
.tree-node i {
margin-right: 6px;
color: var(--text-color);
width: 12px;
text-align: center;
font-size: 10px;
}
.tree-node .folder {
color: #6366f1;
}
.tree-node .file {
color: var(--text-secondary);
}
.tree-node .toggle {
color: #94a3b8;
margin-right: 3px;
font-size: 9px;
}
.tree-content {
flex: 1;
display: flex;
align-items: center;
min-width: 0;
}
.tree-name {
font-weight: 500;
font-size: 13px;
overflow: hidden;
text-overflow: ellipsis;
color: #1e293b;
}
.tree-desc {
color: #64748b;
font-size: 10px;
margin-left: 8px;
font-style: italic;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 180px;
}
.collapsed > ul {
display: none;
}
.collapsed .toggle.fa-chevron-down::before {
content: "\f054";
}
.highlight {
background: linear-gradient(135deg, var(--accent-color), var(--secondary-color));
padding: 0 3px;
border-radius: 3px;
color: #fff;
}
footer {
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
color: white;
padding: 8px 16px;
text-align: center;
font-size: 10px;
border-top: 1px solid var(--border-color);
flex-shrink: 0;
z-index: 10;
}
/* 移动端优化*/
@media (max-width: 768px) {
body {
font-size: 12px;
}
header h1 {
font-size: 16px;
}
header p {
font-size: 11px;
}
.tree ul {
padding-left: 14px;
}
.tree li {
padding: 0.5px 0;
}
.tree-name {
font-size: 12px;
}
.tree-desc {
font-size: 9px;
margin-left: 6px;
max-width: 120px;
}
#searchInput {
width: 140px;
font-size: 11px;
}
.controls button {
font-size: 11px;
padding: 5px 10px;
}
}
/* 超小屏幕优化*/
@media (max-width: 480px) {
body {
font-size: 13px;
}
header h1 {
font-size: 14px;
}
header p {
font-size: 10px;
}
.tree ul {
padding-left: 12px;
}
.tree li {
padding: 0;
}
.tree-node {
padding: 1px 3px;
}
.tree-node i {
margin-right: 4px;
width: 10px;
font-size: 9px;
}
.tree-name {
font-size: 11px;
}
.tree-desc {
font-size: 8px;
margin-left: 4px;
max-width: 90px;
}
.tree-container {
padding: 8px;
}
.controls {
padding: 8px 12px;
}
#searchInput {
width: 120px;
font-size: 10px;
padding: 4px 8px;
}
.controls button {
font-size: 10px;
padding: 4px 8px;
}
}
/* 让描述文字不斜、不断行、显示完整*/
.tree-desc {
font-style: normal !important;
white-space: normal !important;
max-width: none !important;
overflow: visible !important;
text-overflow: unset !important;
display: inline-block !important;
line-height: 1.4 !important;
margin-left: 6px !important;
font-size: 11px !important;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>Bash 内建命令树形结构</h1>
<p>Bash Built-in Commands Tree Structure</p>
</header>
<div class="controls">
<div>
<button id="expandAll"><i class="fas fa-plus-square"></i> 展 开 </button>
<button id="collapseAll"><i class="fas fa-minus-square"></i> 折叠 </button>
</div>
<div>
<input type="text" id="searchInput" placeholder="搜索...">
</div>
</div>
<div class="tree-container">
<div class="tree" id="treeContainer"></div>
</div>
<footer>
<p>© 2025 Bash 内建命令树形结构| Generated by 凉安</p>
</footer>
</div>
<script>
// Bash 命令树形数据
const bashTreeData = [
{
name: "1️⃣目录与路径",
type: "folder",
children: [
{
name: "1.1 位移",
type: "folder",
children: [
{ name: "cd", desc: "change directory ➡️进入指定目录", type: "file" },
{ name: "pushd", desc: "push directory ⬅️把目录压栈并进入", type: "file" },
{ name: "popd", desc: "pop directory 弹出栈顶目录并进入", type: "file" },
{ name: "dirs", desc: "directory stack ️️显示目录栈内容", type: "file" }
]
},
{
name: "1.2 定位",
type: "folder",
children: [
{ name: "pwd", desc: "print working directory 打印当前绝对路径", type: "file" }
]
},
{
name: "1.3 新建",
type: "folder",
children: [
{ name: "mkdir", desc: "make directory 内建递归创建目录", type: "file" }
]
}
]
},
{
name: "2️⃣变量与属性️️️",
type: "folder",
children: [
{
name: "2.1 声明",
type: "folder",
children: [
{ name: "declare", desc: "声明变量作用域/类型 ️️", type: "file" },
{ name: "typeset", desc: " 同declare 旧称 ️️", type: "file" },
{ name: "local", desc: "函数内局部变量 ", type: "file" },
{ name: "readonly", desc: "设变量只读 ", type: "file" }
]
},
{
name: "2.2 导出",
type: "folder",
children: [
{ name: "export", desc: "将变量放进环境 ", type: "file" }
]
},
{
name: "2.3 销毁",
type: "folder",
children: [
{ name: "unset", desc: "删除变量/函数 ️️", type: "file" }
]
}
]
},
{
name: "3️⃣流程与控制",
type: "folder",
children: [
{
name: "3.1 条件",
type: "folder",
children: [
{ name: "if/then/else", desc: "分支结构", type: "file" },
{ name: "case", desc: "多模式匹配 ️️", type: "file" },
{ name: "[[ ]]", desc: "高级测试 ", type: "file" },
{ name: "(( ))", desc: "算术测试 ", type: "file" },
{ name: "test/[", desc: "兼容测试 ", type: "file" }
]
},
{
name: "3.2 循环",
type: "folder",
children: [
{ name: "for", desc: "计数/列表循环 ", type: "file" },
{ name: "while", desc: "条件循环 ", type: "file" },
{ name: "until", desc: "直到条件成立 ", type: "file" }
]
},
{
name: "3.3 跳转",
type: "folder",
children: [
{ name: "break", desc: "退出当前循环⏹️", type: "file" },
{ name: "continue", desc: "跳过本次循环⏭️", type: "file" },
{ name: "return", desc: "函数返回↩️", type: "file" },
{ name: "exit", desc: "脚本退出 ", type: "file" }
]
}
]
},
{
name: "4️⃣输入输出️️️",
type: "folder",
children: [
{
name: "4.1 打印",
type: "folder",
children: [
{ name: "echo", desc: "简单输出 ", type: "file" },
{ name: "printf", desc: "格式化输出 ", type: "file" }
]
},
{
name: "4.2 读取",
type: "folder",
children: [
{ name: "read", desc: "读一行到变量⌨️", type: "file" },
{ name: "mapfile/readarray", desc: "读文件到数组 ", type: "file" }
]
}
]
},
{
name: "5️⃣作业与进程⚙️",
type: "folder",
children: [
{
name: "5.1 前后台",
type: "folder",
children: [
{ name: "bg", desc: "把作业放后台⬅️", type: "file" },
{ name: "fg", desc: "把作业拎前台➡️", type: "file" },
{ name: "jobs", desc: "查看作业列表 ", type: "file" }
]
},
{
name: "5.2 信号",
type: "folder",
children: [
{ name: "kill", desc: "发信号 ", type: "file" },
{ name: "suspend", desc: "挂起shell ⏸️", type: "file" },
{ name: "disown", desc: "从作业表移除 ", type: "file" }
]
},
{
name: "5.3 等待",
type: "folder",
children: [
{ name: "wait", desc: "等子进程结束", type: "file" }
]
},
{
name: "5.4 计时",
type: "folder",
children: [
{ name: "time", desc: "统计命令耗时⏱️", type: "file" },
{ name: "times", desc: "打印shell 累计时间⏲️", type: "file" }
]
}
]
},
{
name: "6️⃣调试与元信息",
type: "folder",
children: [
{
name: "6.1 帮助",
type: "folder",
children: [
{ name: "help", desc: "内建帮助系统", type: "file" },
{ name: "type", desc: "查看命令类型 ", type: "file" },
{ name: "command", desc: "强制跳过别名/函数⚡", type: "file" }
]
},
{
name: "6.2 启用/禁用",
type: "folder",
children: [
{ name: "enable", desc: " 开/关内建 ", type: "file" },
{ name: "builtin", desc: "强制用内建 ", type: "file" }
]
},
{
name: "6.3 历史",
type: "folder",
children: [
{ name: "history", desc: "命令历史 ", type: "file" },
{ name: "fc", desc: "修复/重跑历史 ", type: "file" }
]
}
]
},
{
name: "7️⃣环境与会话",
type: "folder",
children: [
{
name: "7.1 选项",
type: "folder",
children: [
{ name: "set", desc: "开关shell 选项⚙️", type: "file" },
{ name: "shopt", desc: "开关可选特性 ️️", type: "file" }
]
},
{
name: "7.2 别名",
type: "folder",
children: [
{ name: "alias", desc: "建别名 ️️", type: "file" },
{ name: "unalias", desc: "删别名 ️️", type: "file" }
]
},
{
name: "7.3 限制",
type: "folder",
children: [
{ name: "ulimit", desc: "资源上限 ", type: "file" },
{ name: "umask", desc: "默认权限掩码 ", type: "file" }
]
},
{
name: "7.4 登录",
type: "folder",
children: [
{ name: "logout", desc: "退出登录shell ", type: "file" },
{ name: "login", desc: "替换登录(部分系统) ", type: "file" }
]
},
{
name: "7.5 执行",
type: "folder",
children: [
{ name: "source/.", desc: "当前环境执行脚本▶️", type: "file" },
{ name: "exec", desc: "用新进程替换shell ", type: "file" }
]
},
{
name: "7.6 哈希",
type: "folder",
children: [
{ name: "hash", desc: "缓存命令路径⚡", type: "file" }
]
},
{
name: "7.7 陷阱",
type: "folder",
children: [
{ name: "trap", desc: "捕获信号/退出 ", type: "file" }
]
},
{
name: "7.8 求值",
type: "folder",
children: [
{ name: "eval", desc: "字符串当命令执行 ", type: "file" }
]
},
{
name: "7.9 假命令",
type: "folder",
children: [
{ name: "true", desc: "永远返回0 ", type: "file" },
{ name: "false", desc: "永远返回1 ", type: "file" },
{ name: ":", desc: "空命令(冒号) ", type: "file" }
]
},
{
name: "7.10 行编辑器",
type: "folder",
children: [
{ name: "bind", desc: "配置readline 快捷键⌨️", type: "file" },
{ name: "caller", desc: "打印调用栈(调试) ", type: "file" }
]
},
{
name: "7.11 补全",
type: "folder",
children: [
{ name: "compgen", desc: "生成补全候选 ", type: "file" },
{ name: "complete", desc: "定义补全规则 ", type: "file" },
{ name: "compopt", desc: "修改补全行为 ️️", type: "file" }
]
},
{
name: "7.12 协同进程",
type: "folder",
children: [
{ name: "coproc", desc: "建立协程管道 ", type: "file" }
]
},
{
name: "7.13 参数解析",
type: "folder",
children: [
{ name: "getopts", desc: "解析位置参数 ", type: "file" }
]
},
{
name: "7.14 变量列表",
type: "folder",
children: [
{ name: "variables", desc: "打印特殊变量说明 ", type: "file" }
]
}
]
}
];
// 创建树节点的函数
function createTreeNode(data) {
const li = document.createElement('li');
const nodeDiv = document.createElement('div');
nodeDiv.className = 'tree-node';
// 添加折叠图标(仅文件夹)
if (data.type === 'folder') {
const toggleIcon = document.createElement('i');
toggleIcon.className = 'fas fa-chevron-down toggle';
nodeDiv.appendChild(toggleIcon);
}
// 添加文件夹/文件图标
const icon = document.createElement('i');
icon.className = data.type === 'folder' ? 'fas fa-folder folder' : 'fas fa-file file';
nodeDiv.appendChild(icon);
// 添加内容区域
const contentDiv = document.createElement('div');
contentDiv.className = 'tree-content';
const nameSpan = document.createElement('span');
nameSpan.className = 'tree-name';
nameSpan.textContent = data.name;
contentDiv.appendChild(nameSpan);
if (data.desc) {
const descSpan = document.createElement('span');
descSpan.className = 'tree-desc';
descSpan.textContent = data.desc;
contentDiv.appendChild(descSpan);
}
nodeDiv.appendChild(contentDiv);
li.appendChild(nodeDiv);
// 递归创建子节点
if (data.children && data.children.length > 0) {
const ul = document.createElement('ul');
data.children.forEach(child => {
ul.appendChild(createTreeNode(child));
});
li.appendChild(ul);
}
return li;
}
// 初始化树形结构
function initTree() {
const treeContainer = document.getElementById('treeContainer');
const ul = document.createElement('ul');
bashTreeData.forEach(item => {
ul.appendChild(createTreeNode(item));
});
treeContainer.appendChild(ul);
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
// 初始化树形结构
initTree();
// 使用事件委托处理折叠/展开
document.getElementById('treeContainer').addEventListener('click', function(e) {
const treeNode = e.target.closest('.tree-node');
if (!treeNode) return;
const folder = treeNode.querySelector('.folder');
if (!folder) return;
const li = treeNode.parentElement;
li.classList.toggle('collapsed');
});
// 展开全部按钮
document.getElementById('expandAll').addEventListener('click', function() {
document.querySelectorAll('.tree li.collapsed').forEach(li => {
li.classList.remove('collapsed');
});
});
// 折叠全部按钮
document.getElementById('collapseAll').addEventListener('click', function() {
document.querySelectorAll('.tree li:has(.folder)').forEach(li => {
if (!li.parentElement.classList.contains('tree')) {
li.classList.add('collapsed');
}
});
});
// 搜索功能
document.getElementById('searchInput').addEventListener('input', function(e) {
const searchTerm = e.target.value.toLowerCase();
// 清除之前的高亮
document.querySelectorAll('.highlight').forEach(el => {
el.classList.remove('highlight');
});
if (searchTerm === '') return;
// 搜索并高亮匹配项
document.querySelectorAll('.tree-node').forEach(node => {
const text = node.textContent.toLowerCase();
if (text.includes(searchTerm)) {
node.querySelector('.tree-name').classList.add('highlight');
// 展开父节点
let parent = node.closest('li');
while (parent && !parent.classList.contains('tree')) {
parent.classList.remove('collapsed');
parent = parent.parentElement.closest('li');
}
}
});
});
});
</script>
<script>
(function() {
// 创建SVG 图标定义
const svgIcons = {
'fa-plus-square': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M208 344c-13.3 0-24-10.7-24-24v-48H136c-13.3 0-24-10.7-24-24s10.7-24 24-24h48v-48c0-13.3 10.7-24 24-24s24 10.7 24 24v48h48c13.3 0 24 10.7 24 24s-10.7 24-24 24h-48v48c0 13.3-10.7 24-24 24zm240-128c0 52.5-42.5 95-95 95H395c-52.5 0-95-42.5-95-95V395c0-52.5 42.5-95 95-95h58c52.5 0 95 42.5 95 95v58zm-48 0c0-26.5-21.5-48-48-48h-58c-26.5 0-48 21.5-48 48v58c0 26.5 21.5 48 48 48h58c26.5 0 48-21.5 48-48v-58z"/></svg>',
'fa-minus-square': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M392 256H56c-13.3 0-24-10.7-24-24s10.7-24 24-24h336c13.3 0 24 10.7 24 24s-10.7 24-24 24zm48-160c0 52.5-42.5 95-95 95H395c-52.5 0-95-42.5-95-95V395c0-52.5 42.5-95 95-95h58c52.5 0 95 42.5 95 95v58zm-48 0c0-26.5-21.5-48-48-48h-58c-26.5 0-48 21.5-48 48v58c0 26.5 21.5 48 48 48h58c26.5 0 48-21.5 48-48v-58z"/></svg>',
'fa-chevron-down': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M224.8 414c-6.7 0-13.5-2.8-18.4-7.8l-172-172c-9.9-9.9-9.9-26 0-36.2s26.1-9.9 36.2 0l154.1 154.1 154.1-154.1c9.9-9.9 26.1-9.9 36.2 0s9.9 26.1 0 36.2l-172 172c-4.9 5-11.7 7.8-18.4 7.8z"/></svg>',
'fa-folder': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M464 128H272l-64-64H48C21.5 64 0 85.5 0 112v288c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48V176c0-26.5-21.5-48-48-48zm0 32v288H48V112h169.1l64.4 64.4H464z"/></svg>',
'fa-file': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M369.9 97.9L86.04 3.57C81.5 1.82 76.56 0 71.69 0H64C28.65 0 0 28.65 0 64v384c0 35.35 28.65 64 64 64h320c35.35 0 64-28.65 64-64V133.9c0-8.8-3.6-17.3-9.9-23.9zM256 51.9V128H64V51.9h192zm128 448.1H164v35.9h209.9v-35.9zm64-48.1H164v35.9h273.9v-35.9zm-0.1-240.1 H164v240.1h280z"/></svg>'
};
// 创建样式规则
const style = document.createElement('style');
let css = `
.fas {
display: inline-block;
width: 1em;
height: 1em;
fill: currentColor;
vertical-align: middle;
}`;
// 为每个图标生成CSS 规则
for (const className in svgIcons) {
css += `
.${className}::before {
content: '';
display: inline-block;
width: 1em;
height: 1em;
background-image: url("data:image/svg+xml,${encodeURIComponent(svgIcons[className])}");
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}`;
}
style.textContent = css;
document.head.appendChild(style);
})();
</script>
</body>
</html>