feat: add script catalog and -h help for all dotfile scripts

Introduce ff script -h with auto descriptions, shared help.sh, and usage flags across script/*.sh.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-25 15:09:35 +08:00
parent 1f6b042b26
commit 67291a9a50
36 changed files with 1056 additions and 442 deletions
+27
View File
@@ -1 +1,28 @@
#!/bin/bash
# 清理 Homebrew 缓存与无用文件
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: brew-clean
执行 Homebrew 清理(brew cleanup),删除旧版本与缓存。
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -euo pipefail
if ! command -v brew &>/dev/null; then
echo "错误: 未找到 brew,请先安装 Homebrew" >&2
exit 1
fi
brew cleanup
+22
View File
@@ -1,3 +1,25 @@
#!/bin/bash
# 使用国内镜像安装 Homebrew
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: brew-install
通过中科大镜像安装 Homebrew(设置 HOMEBREW_* 镜像环境变量后执行官方安装脚本)。
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -euo pipefail
export HOMEBREW_BREW_GIT_REMOTE="https://mirrors.ustc.edu.cn/brew.git"
export HOMEBREW_CORE_GIT_REMOTE="https://mirrors.ustc.edu.cn/homebrew-core.git"
export HOMEBREW_BOTTLE_DOMAIN="https://mirrors.ustc.edu.cn/homebrew-bottles"
+46 -20
View File
@@ -1,31 +1,57 @@
#!/usr/bin/env bash
# Copy stdin to the system clipboard (macOS / Linux X11 / Linux Wayland).
# 将标准输入复制到系统剪贴板(macOS / Linux X11 / Wayland)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: clip-copy
从 stdin 读取内容并写入系统剪贴板。
支持:
macOS: pbcopy
Wayland: wl-copy
X11: xclip / xsel
选项:
-h, --help 显示此帮助
示例:
echo hello | clip-copy
cat file.txt | clip-copy
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -euo pipefail
if command -v pbcopy >/dev/null 2>&1; then
pbcopy
pbcopy
elif [ "${XDG_SESSION_TYPE:-}" = wayland ] || [ -n "${WAYLAND_DISPLAY:-}" ]; then
if command -v wl-copy >/dev/null 2>&1; then
wl-copy --no-newline
else
echo "clip-copy: wl-copy not found (Wayland session)" >&2
exit 1
fi
if command -v wl-copy >/dev/null 2>&1; then
wl-copy --no-newline
else
echo "clip-copy: wl-copy not found (Wayland session)" >&2
exit 1
fi
elif [ -n "${DISPLAY:-}" ]; then
if command -v xclip >/dev/null 2>&1; then
xclip -selection clipboard
elif command -v xsel >/dev/null 2>&1; then
xsel --clipboard --input
else
echo "clip-copy: xclip or xsel not found (DISPLAY=$DISPLAY)" >&2
exit 1
fi
if command -v xclip >/dev/null 2>&1; then
xclip -selection clipboard
elif command -v xsel >/dev/null 2>&1; then
xsel --clipboard --input
else
echo "clip-copy: xclip or xsel not found (DISPLAY=$DISPLAY)" >&2
exit 1
fi
elif command -v xclip >/dev/null 2>&1; then
xclip -selection clipboard
xclip -selection clipboard
elif command -v xsel >/dev/null 2>&1; then
xsel --clipboard --input
xsel --clipboard --input
else
echo "clip-copy: no clipboard tool (pbcopy / wl-copy / xclip / xsel)" >&2
exit 1
echo "clip-copy: no clipboard tool (pbcopy / wl-copy / xclip / xsel)" >&2
exit 1
fi
+11
View File
@@ -0,0 +1,11 @@
# 供 script/*.sh source:统一处理 -h / --help
# 调用方需先定义 usage() 函数
dotfile_help_requested() {
[[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]
}
dotfile_show_help() {
usage
exit 0
}
+25 -9
View File
@@ -1,21 +1,40 @@
#!/bin/bash
# 执行命令并在失败时通过飞书 Webhook 发送通知
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: croncheck <command> [args...]
执行给定命令;若退出码非 0,向配置的飞书 Webhook 发送失败通知。
最终以原命令的退出码退出。
选项:
-h, --help 显示此帮助
示例:
croncheck /path/to/backup.sh
croncheck docker compose up -d
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
# 检查参数数量
if [ "$#" -lt 1 ]; then
echo "Usage: $0 <command> [command_args...]"
echo "错误: 缺少要执行的命令" >&2
usage
exit 1
fi
# 获取 webhook URL
WEBHOOK_URL="https://open.feishu.cn/open-apis/bot/v2/hook/808eafd8-a79f-4af0-b730-8442cf15933b"
# 执行命令并捕获输出
OUTPUT=$("$@" 2>&1)
EXIT_CODE=$?
# 如果命令失败,发送 webhook 通知
if [ $EXIT_CODE -ne 0 ]; then
# 准备 JSON 数据
JSON_DATA=$(cat <<EOF
{
"msg_type": "text",
@@ -25,10 +44,7 @@ if [ $EXIT_CODE -ne 0 ]; then
}
EOF
)
# 发送 webhook
curl -s -X POST -H "Content-Type: application/json" -d "$JSON_DATA" "$WEBHOOK_URL"
fi
# 退出,使用原命令的退出码
exit $EXIT_CODE
+25 -4
View File
@@ -1,17 +1,38 @@
#!/bin/bash
# 将 Cursor 用户配置链接到 dotfile(macOS)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: cursor-init
链接 ~/.dotfile/cursor/config/ 下的 settings.json、keybindings.json
到 Cursor 用户目录(macOS)。
已有文件会备份为 *.bak。
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -euo pipefail
echo 'Cursor config init'
# init settings.json
src="$HOME/Library/Application Support/Cursor/User/settings.json"
if [ -f "$src" ]; then
mv "$src" "$src.bak"
mv "$src" "$src.bak"
fi
ln -s "$HOME/.dotfile/cursor/config/settings.json" "$src"
# init keybindings.json
src="$HOME/Library/Application Support/Cursor/User/keybindings.json"
if [ -f "$src" ]; then
mv "$src" "$src.bak"
mv "$src" "$src.bak"
fi
ln -s "$HOME/.dotfile/cursor/config/keybindings.json" "$src"
+19 -1
View File
@@ -1,8 +1,26 @@
#!/bin/bash
# Debian 国内镜像源更换脚本
# Debian 国内镜像源更换脚本(交互式选择镜像)
# 支持 Debian 9/10/11/12/13 (stretch/buster/bullseye/bookworm/trixie)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: sudo debian-init
交互式将 Debian apt 源更换为国内镜像(需 root)。
自动检测版本代号,备份原 sources.list。
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -e
# 颜色定义
+18
View File
@@ -3,6 +3,24 @@
# Debian 一键更换清华镜像源脚本 (DEB822 格式)
# 支持 Debian 12 (bookworm)、13 (trixie)、14 (forky) 及后续版本
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: sudo debian-tuna
将 Debian apt 源一键替换为清华 DEB822 格式源(需 root)。
会处理 /etc/apt/sources.list.d/debian.sources 与旧版 sources.list。
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -e
# 颜色定义
+1
View File
@@ -1,4 +1,5 @@
#!/bin/bash
# 查询目录大小(du 封装,支持排序与 Top N)
set -eu
+22 -3
View File
@@ -1,7 +1,26 @@
#!/bin/bash
# 清理 macOS / Linux 系统 DNS 缓存
# 用法:
# ./dns-clean.sh # 清理 macOS / Linux 系统 DNS 缓存
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: dns-clean
按当前操作系统清理 DNS 缓存:
macOS: dscacheutil + mDNSResponder
Linux: systemd-resolved / nscd / dnsmasq / unbound(自动检测)
选项:
-h, --help 显示此帮助
说明: 非 root 时会自动使用 sudo。
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -e
@@ -68,7 +87,7 @@ flush_linux() {
case "$(uname -s)" in
Darwin) flush_macos ;;
Linux) flush_linux ;;
Linux) flush_linux ;;
*)
echo "错误: 不支持的操作系统: $(uname -s)"
exit 1
+23
View File
@@ -1,2 +1,25 @@
#!/bin/bash
# 清理 Docker 未使用的镜像、容器与缓存(docker system prune -a)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: docker-clean
执行 docker system prune -a,删除未使用的镜像、容器、网络等。
选项:
-h, --help 显示此帮助
警告: 会删除未使用的镜像,请确认无重要 dangling 资源。
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -euo pipefail
docker system prune -a
+9 -5
View File
@@ -1,7 +1,9 @@
#!/bin/bash
# 将用户加入 docker 组(免 sudo 使用 docker)
# 用法: sudo docker-group <user>
# 示例: sudo docker-group xuser
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
set -euo pipefail
@@ -17,12 +19,14 @@ usage() {
说明:
- 用户需重新登录或 newgrp docker 后生效
- 安装 Docker 时 docker-install.sh 只会把当时的 $USER 加入组
选项:
-h, --help 显示此帮助
EOF
exit 1
}
[[ "${1:-}" == "-h" || "${1:-}" == "--help" ]] && usage
[[ $# -eq 1 ]] || usage
dotfile_help_requested "${1:-}" && dotfile_show_help
[[ $# -eq 1 ]] || { usage; exit 1; }
if [[ $EUID -ne 0 ]]; then
echo "错误: 请使用 sudo 运行,例如: sudo $0 $1"
+23 -5
View File
@@ -1,4 +1,27 @@
#!/bin/bash
# 在 Debian/Ubuntu 上安装 Docker CE(支持国内/国外镜像源)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: docker-install
在 Debian 或 Ubuntu 上安装 Docker CE 及 compose/buildx 插件。
根据环境变量 CN_REGION 选择镜像源:
CN_REGION=1 清华镜像
其他 Docker 官方源
安装完成后将当前用户加入 docker 组。
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -e
@@ -38,8 +61,6 @@ install_prerequisites() {
sudo apt-get install -y ca-certificates curl gnupg lsb-release
}
#################################################################
# 国内安装(使用清华镜像)
install_docker_cn() {
local repo_base="https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/${DISTRO}"
local keyring="/usr/share/keyrings/docker-archive-keyring.gpg"
@@ -56,8 +77,6 @@ install_docker_cn() {
sudo usermod -aG docker "$USER"
}
#################################################################
# 国外安装(使用官方源)
install_docker_intl() {
local repo_base="https://download.docker.com/linux/${DISTRO}"
local keyring="/etc/apt/keyrings/docker.asc"
@@ -81,7 +100,6 @@ detect_distro
remove_conflicting_packages
install_prerequisites
# 根据环境变量选择安装方式(须在函数定义之后调用)
if [ "$CN_REGION" = "1" ]; then
echo "[INFO] 国内环境,使用清华镜像安装 Docker (${DISTRO}/${CODENAME})"
install_docker_cn
+21
View File
@@ -1,4 +1,25 @@
#!/bin/bash
# 下载 Fira Code 字体压缩包并打开所在目录(需手动安装)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: firacode-install
从 GitHub 下载 Fira Code v6.2 到 ~/Downloads/,并打开 Finder/文件管理器。
需在图形界面中解压并安装字体文件。
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -euo pipefail
cd ~/Downloads/
wget https://github.com/tonsky/FiraCode/releases/download/6.2/Fira_Code_v6.2.zip
+26 -14
View File
@@ -1,4 +1,25 @@
#!/bin/bash
# 初始化 Fish:wrapper 配置、链接 functions/completions、安装 fisher/z
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: fish-init
1. 确保 ~/.config/fish/config.fish source dotfile/fish/default.fish
2. 链接 dotfile 中 fish functions 与 completions
3. 安装 fisher、z 插件
4. 将默认 shell 设为 fish
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
LOCAL_CONFIG="$HOME/.config/fish/config.fish"
DEFAULT_PATH="$HOME/.dotfile/fish/default.fish"
@@ -8,43 +29,36 @@ mkdir -p "$HOME/.config/fish"
echo 'Setup fish config.fish wrapper'
# 旧版迁移:如果 config.fish 是指向 dotfile 的 symlink(老布局),移除
if [ -L "$LOCAL_CONFIG" ]; then
link_target=$(readlink "$LOCAL_CONFIG")
case "$link_target" in
*/dotfile/fish/config.fish|*/dotfile/fish/default.fish)
*/dotfile/fish/config.fish | */dotfile/fish/default.fish)
echo " Removing legacy symlink: $LOCAL_CONFIG -> $link_target"
rm "$LOCAL_CONFIG"
;;
esac
fi
# 不存在 -> 创建只含一行 source 的本地 wrapper
# 存在但未 source default.fish -> 在文件顶部插入 source 行
# 已 source -> 跳过
if [ ! -f "$LOCAL_CONFIG" ]; then
echo "$SOURCE_LINE" > "$LOCAL_CONFIG"
echo "$SOURCE_LINE" >"$LOCAL_CONFIG"
echo " Created $LOCAL_CONFIG (sources default.fish)"
elif ! grep -qE '^[[:space:]]*source.*default\.fish' "$LOCAL_CONFIG"; then
tmp=$(mktemp)
{ echo "$SOURCE_LINE"; echo; cat "$LOCAL_CONFIG"; } > "$tmp"
{ echo "$SOURCE_LINE"; echo; cat "$LOCAL_CONFIG"; } >"$tmp"
mv "$tmp" "$LOCAL_CONFIG"
echo " Prepended source line to existing $LOCAL_CONFIG"
else
echo " $LOCAL_CONFIG already sources default.fish, skip"
fi
# 确保目标目录存在
echo 'Link fish functions and completions'
mkdir -p "$HOME/.config/fish/functions"
mkdir -p "$HOME/.config/fish/completions"
# 链接 functions 目录下的所有文件
for file in $HOME/.dotfile/fish/functions/*.fish; do
if [ -f "$file" ]; then
filename=$(basename "$file")
target="$HOME/.config/fish/functions/$filename"
# 如果已存在且不是符号链接,备份
if [ -f "$target" ] && [ ! -L "$target" ]; then
mv "$target" "$target.bak"
fi
@@ -53,12 +67,10 @@ for file in $HOME/.dotfile/fish/functions/*.fish; do
fi
done
# 链接 completions 目录下的所有文件
for file in $HOME/.dotfile/fish/completions/*.fish; do
if [ -f "$file" ]; then
filename=$(basename "$file")
target="$HOME/.config/fish/completions/$filename"
# 如果已存在且不是符号链接,备份
if [ -f "$target" ] && [ ! -L "$target" ]; then
mv "$target" "$target.bak"
fi
@@ -72,5 +84,5 @@ fish -c "fisher install jethrokuan/z"
echo 'Set fish as default shell'
fishpath=$(which fish)
echo $fishpath | sudo tee -a /etc/shells
chsh -s $fishpath
echo "$fishpath" | sudo tee -a /etc/shells
chsh -s "$fishpath"
+52 -26
View File
@@ -1,83 +1,109 @@
#!/usr/bin/env python3
# 下载并安装 Sarasa Nerd / Fira Code 字体到用户字体目录
import argparse
import os
import sys
import platform
import subprocess
from typing import Dict, List, Optional
import sys
import urllib.request
import zipfile
import shutil
from typing import Dict, List
def usage_text() -> str:
return """用法: font-install
下载并安装以下字体到用户字体目录:
- Sarasa Gothic Nerd (SC)
- Fira Code
macOS: ~/Library/Fonts
Linux: ~/.local/share/fonts(安装后尝试 fc-cache)
选项:
-h, --help 显示此帮助
"""
def get_font_dir() -> str:
"""根据操作系统确定字体安装目录"""
system = platform.system()
if system == "Darwin": # macOS
if system == "Darwin":
return os.path.expanduser("~/Library/Fonts")
elif system == "Linux":
if system == "Linux":
return os.path.expanduser("~/.local/share/fonts")
else:
raise OSError(f"不支持的操作系统: {system}")
raise OSError(f"不支持的操作系统: {system}")
def check_command(command: str) -> bool:
"""检查命令是否存在"""
return shutil.which(command) is not None
def download_file(url: str, dest_path: str) -> None:
"""下载文件到指定路径"""
try:
urllib.request.urlretrieve(url, dest_path)
except Exception as e:
print(f"下载失败: {e}")
sys.exit(1)
def get_top_level_dirs(zip_file: zipfile.ZipFile) -> List[str]:
"""获取 ZIP 文件中的顶级目录"""
return list(set(item.split('/')[0] for item in zip_file.namelist() if '/' in item))
return list(set(item.split("/")[0] for item in zip_file.namelist() if "/" in item))
def has_single_top_dir(zip_file: zipfile.ZipFile) -> bool:
"""检查 ZIP 文件是否只有一个顶级目录"""
top_dirs = get_top_level_dirs(zip_file)
return len(top_dirs) == 1 and all(name.startswith(top_dirs[0] + '/') for name in zip_file.namelist())
return len(top_dirs) == 1 and all(
name.startswith(top_dirs[0] + "/") for name in zip_file.namelist()
)
def unzip_file(zip_path: str, font_name: str) -> None:
"""解压文件到指定路径,根据 ZIP 文件结构决定是否创建顶级目录"""
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
with zipfile.ZipFile(zip_path, "r") as zip_ref:
if has_single_top_dir(zip_ref):
# ZIP 文件有单一顶级目录,直接解压
zip_ref.extractall("/tmp")
print(f"已解压 {font_name} 到现有顶级目录")
else:
# 没有单一顶级目录,创建一个以字体名命名的目录
font_dir = os.path.join("/tmp", font_name)
os.makedirs(font_dir, exist_ok=True)
for file in zip_ref.namelist():
if not file.startswith('__MACOSX'): # 排除 macOS 系统文件
if not file.startswith("__MACOSX"):
zip_ref.extract(file, font_dir)
print(f"已解压 {font_name} 并创建新的顶级目录")
def install_font(font_name: str, font_dir: str) -> None:
"""安装字体到指定目录"""
# find ttf files to copy to the font_dir
ttf_files = [file for file in os.listdir(f"/tmp/{font_name}") if file.endswith(".ttf")]
ttf_files = [
file for file in os.listdir(f"/tmp/{font_name}") if file.endswith(".ttf")
]
for ttf_file in ttf_files:
shutil.copy(f"/tmp/{font_name}/{ttf_file}", font_dir)
print(f"已安装 {font_name} 到 {font_dir}")
def refresh_font_cache() -> None:
"""在 Linux 系统上刷新字体缓存"""
if platform.system() == "Linux" and check_command("fc-cache"):
subprocess.run(["fc-cache", "-f"])
subprocess.run(["fc-cache", "-f"], check=False)
print("字体缓存已刷新。")
else:
print("警告:无法刷新字体缓存。您可能需要手动刷新。")
def main() -> None:
parser = argparse.ArgumentParser(
description="下载并安装 Sarasa Nerd / Fira Code 字体",
add_help=False,
)
parser.add_argument("-h", "--help", action="store_true", help="显示帮助")
args, _ = parser.parse_known_args()
if args.help:
print(usage_text())
return
fonts: Dict[str, str] = {
"SarasaNerd":"https://github.com/jonz94/Sarasa-Gothic-Nerd-Fonts/releases/download/v1.0.23-0/sarasa-fixed-sc-nerd-font.zip",
"FiraCode": "https://github.com/tonsky/FiraCode/releases/download/6.2/Fira_Code_v6.2.zip"
"SarasaNerd": "https://github.com/jonz94/Sarasa-Gothic-Nerd-Fonts/releases/download/v1.0.23-0/sarasa-fixed-sc-nerd-font.zip",
"FiraCode": "https://github.com/tonsky/FiraCode/releases/download/6.2/Fira_Code_v6.2.zip",
}
try:
@@ -99,6 +125,6 @@ def main() -> None:
refresh_font_cache()
print("安装完成。请重启您的终端或应用程序以使用新字体。")
if __name__ == "__main__":
main()
+22 -5
View File
@@ -1,4 +1,26 @@
#!/bin/bash
# 将 Ghostty 配置链接到 dotfile(macOS / Linux)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: ghostty-init
将 ~/.dotfile/ghostty/config.ghostty 软链接到 Ghostty 配置目录:
macOS: ~/Library/Application Support/com.mitchellh.ghostty/
Linux: $XDG_CONFIG_HOME/ghostty/
已有配置会备份为 *.backup.<时间戳>。
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -e
@@ -9,7 +31,6 @@ NC='\033[0m'
SRC="$HOME/.dotfile/ghostty/config.ghostty"
# 根据平台确定目标路径
if [[ "$(uname)" == "Darwin" ]]; then
DEST="$HOME/Library/Application Support/com.mitchellh.ghostty/config.ghostty"
else
@@ -20,22 +41,18 @@ fi
echo -e "${YELLOW}初始化 Ghostty 配置...${NC}"
echo -e "${YELLOW}目标路径:$DEST${NC}"
# 目标目录不存在则创建
mkdir -p "$(dirname "$DEST")"
# 已经是指向正确位置的软链接,无需操作
if [ -L "$DEST" ] && [ "$(readlink -f "$DEST")" = "$(readlink -f "$SRC")" ]; then
echo -e "${GREEN}软链接已存在且指向正确位置,无需操作。${NC}"
exit 0
fi
# 存在旧文件/目录则备份
if [ -e "$DEST" ]; then
BACKUP="${DEST}.backup.$(date +%Y%m%d%H%M%S)"
mv "$DEST" "$BACKUP"
echo -e "${YELLOW}已将现有配置备份到 $BACKUP${NC}"
elif [ -L "$DEST" ]; then
# 损坏的旧软链接
rm "$DEST"
fi
+24 -4
View File
@@ -1,11 +1,31 @@
#!/bin/bash
# 将 ~/.gitconfig 链接到 dotfile,并设置 Linux 凭据脚本可执行
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: git-init
备份已有 ~/.gitconfig,软链接到 ~/.dotfile/git/.gitconfig。
同时为 git-credential-linux.sh 添加可执行权限。
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -euo pipefail
echo 'Init git config'
src=$HOME/.gitconfig
if [ -f $src ]; then
mv $src $src.bak
if [ -f "$src" ]; then
mv "$src" "$src.bak"
fi
ln -s $HOME/.dotfile/git/.gitconfig $src
ln -s "$HOME/.dotfile/git/.gitconfig" "$src"
chmod +x "$HOME/.dotfile/git/git-credential-linux.sh"
+21 -22
View File
@@ -1,32 +1,31 @@
#!/bin/bash
# 安装 gvm(Go 版本管理)并配置 fish 与默认 Go 版本
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: gvm-install
1. 安装 gvm
2. 为 fish 安装 fish-gvm、bass 插件
3. 安装并设置 go1.24.0 为默认版本
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -e
# install gvm
bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
# install gvm on fish
fish -c "fisher install JGAntunes/fish-gvm"
fish -c "fisher install edc/bass"
# install go
fish -c "gvm install go1.24.0 -B"
fish -c "gvm use go1.24.0 --default"
# # install neovim
# os_arch=$(uname -s)-$(uname -m)
# case $os_arch in
# "Darwin-x86_64")
# cd /usr/local
# wget https://golang.google.cn/dl/go1.23.2.linux-amd64.tar.gz
# tar zxvf go1.23.2.linux-amd64.tar.gz
# ;;
# "Linux-x86_64"|"Linux-arm64")
# cd /tmp
# rm -rf nvim-linux64.tar.gz
# wget https://go.dev/dl/go1.23.2.linux-amd64.tar.gz
# tar zxvf go1.23.2.linux-amd64.tar.gz
# mv go /usr/local/
# sudo ln -s /usr/local/go/bin/go/usr/local/bin/go
# ;;
# esac
+20 -3
View File
@@ -1,9 +1,26 @@
#!/bin/bash
# 初始化默认用户脚本
# 用于创建 ace 用户并给予 sudo 权限
# 初始化默认用户脚本:创建 ace 用户并给予 sudo 权限
set -e # 遇到错误时立即退出
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: sudo init-default-user
创建用户 ace(若不存在),设置密码,加入 sudo 组,
并复制 ~/.dotfile 到该用户家目录。
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -e
# 检查是否以 root 身份运行
if [[ $EUID -ne 0 ]]; then
+86 -64
View File
@@ -1,4 +1,27 @@
#!/bin/bash
# 安装 lazygit(brew / apt / GitHub Release 二进制)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: lazygit-install
按顺序尝试安装 lazygit:
1. Homebrew (macOS/Linux)
2. apt (Debian/Ubuntu)
3. 从 GitHub Release 下载到 ~/.local/bin
若已安装则打印版本并退出。
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -e
@@ -8,89 +31,88 @@ RED='\033[0;31m'
NC='\033[0m'
if command -v lazygit &>/dev/null; then
echo -e "${GREEN}lazygit 已安装:${NC}"
lazygit --version
exit 0
echo -e "${GREEN}lazygit 已安装:${NC}"
lazygit --version
exit 0
fi
install_via_brew() {
if ! command -v brew &>/dev/null; then
return 1
fi
echo -e "${YELLOW}使用 Homebrew 安装 lazygit...${NC}"
brew install lazygit
if ! command -v brew &>/dev/null; then
return 1
fi
echo -e "${YELLOW}使用 Homebrew 安装 lazygit...${NC}"
brew install lazygit
}
install_via_apt() {
if ! command -v apt-get &>/dev/null; then
return 1
fi
echo -e "${YELLOW}使用 apt 安装 lazygit...${NC}"
sudo apt-get update
sudo apt-get install -y lazygit
if ! command -v apt-get &>/dev/null; then
return 1
fi
echo -e "${YELLOW}使用 apt 安装 lazygit...${NC}"
sudo apt-get update
sudo apt-get install -y lazygit
}
# 从 GitHub Release 解压到 ~/.local/bin(与 nvim/init.lua 中的 PATH 一致)
install_via_release() {
local ver
ver=$(curl -fsSL "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" |
grep '"tag_name":' |
sed -E 's/.*"v([^"]+)".*/\1/')
if [[ -z "$ver" ]]; then
echo -e "${RED}无法解析 lazygit 最新版本号${NC}" >&2
return 1
fi
local ver
ver=$(curl -fsSL "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" |
grep '"tag_name":' |
sed -E 's/.*"v([^"]+)".*/\1/')
if [[ -z "$ver" ]]; then
echo -e "${RED}无法解析 lazygit 最新版本号${NC}" >&2
return 1
fi
local os_raw arch_raw asset url
os_raw=$(uname -s)
arch_raw=$(uname -m)
local os_raw arch_raw asset url
os_raw=$(uname -s)
arch_raw=$(uname -m)
case "${os_raw}-${arch_raw}" in
Darwin-arm64) asset="lazygit_${ver}_Darwin_arm64.tar.gz" ;;
Darwin-x86_64) asset="lazygit_${ver}_Darwin_x86_64.tar.gz" ;;
Linux-x86_64) asset="lazygit_${ver}_Linux_x86_64.tar.gz" ;;
Linux-aarch64 | Linux-arm64) asset="lazygit_${ver}_Linux_arm64.tar.gz" ;;
*)
echo -e "${RED}当前平台不支持自动下载二进制: ${os_raw} ${arch_raw}${NC}" >&2
return 1
;;
esac
case "${os_raw}-${arch_raw}" in
Darwin-arm64) asset="lazygit_${ver}_Darwin_arm64.tar.gz" ;;
Darwin-x86_64) asset="lazygit_${ver}_Darwin_x86_64.tar.gz" ;;
Linux-x86_64) asset="lazygit_${ver}_Linux_x86_64.tar.gz" ;;
Linux-aarch64 | Linux-arm64) asset="lazygit_${ver}_Linux_arm64.tar.gz" ;;
*)
echo -e "${RED}当前平台不支持自动下载二进制: ${os_raw} ${arch_raw}${NC}" >&2
return 1
;;
esac
url="https://github.com/jesseduffield/lazygit/releases/download/v${ver}/${asset}"
local tmpdir dest_bin
tmpdir=$(mktemp -d)
dest_bin="${HOME}/.local/bin"
url="https://github.com/jesseduffield/lazygit/releases/download/v${ver}/${asset}"
local tmpdir dest_bin
tmpdir=$(mktemp -d)
dest_bin="${HOME}/.local/bin"
echo -e "${YELLOW}下载 lazygit v${ver} (${asset})...${NC}"
curl -fsSL -o "${tmpdir}/${asset}" "${url}"
tar -xzf "${tmpdir}/${asset}" -C "${tmpdir}"
echo -e "${YELLOW}下载 lazygit v${ver} (${asset})...${NC}"
curl -fsSL -o "${tmpdir}/${asset}" "${url}"
tar -xzf "${tmpdir}/${asset}" -C "${tmpdir}"
mkdir -p "${dest_bin}"
mv -f "${tmpdir}/lazygit" "${dest_bin}/lazygit"
chmod +x "${dest_bin}/lazygit"
rm -rf "${tmpdir}"
mkdir -p "${dest_bin}"
mv -f "${tmpdir}/lazygit" "${dest_bin}/lazygit"
chmod +x "${dest_bin}/lazygit"
rm -rf "${tmpdir}"
echo -e "${GREEN}已安装到 ${dest_bin}/lazygit${NC}"
if [[ ":${PATH}:" != *":${dest_bin}:"* ]]; then
echo -e "${YELLOW}提示: 请将 ${dest_bin} 加入 PATH(例如在 ~/.zshrc 中 export PATH=\"\$HOME/.local/bin:\$PATH\")${NC}"
fi
echo -e "${GREEN}已安装到 ${dest_bin}/lazygit${NC}"
if [[ ":${PATH}:" != *":${dest_bin}:"* ]]; then
echo -e "${YELLOW}提示: 请将 ${dest_bin} 加入 PATH${NC}"
fi
}
main() {
if install_via_brew; then
:
elif install_via_apt; then
:
elif install_via_release; then
:
else
echo -e "${RED}lazygit 安装失败:未找到 brew/apt,且当前平台无法使用官方二进制发布包。${NC}" >&2
exit 1
fi
if install_via_brew; then
:
elif install_via_apt; then
:
elif install_via_release; then
:
else
echo -e "${RED}lazygit 安装失败${NC}" >&2
exit 1
fi
echo -e "${GREEN}lazygit 安装完成:${NC}"
command -v lazygit
lazygit --version
echo -e "${GREEN}lazygit 安装完成:${NC}"
command -v lazygit
lazygit --version
}
main
+48 -34
View File
@@ -1,15 +1,34 @@
#!/bin/bash
source $HOME/.dotfile/script/common/os-arch.sh
# 下载并安装 mihomo 代理内核到 /usr/local/bin
# 检查并安装 gunzip
function check_gunzip() {
if ! command -v gunzip &> /dev/null; then
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: mihomo-install
根据当前 OS/架构从镜像下载 mihomo 二进制,安装到 /usr/local/bin/mihomo。
支持 darwin/linux 的 amd64/arm64。
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
source "$SCRIPT_DIR/common/os-arch.sh"
check_gunzip() {
if ! command -v gunzip &>/dev/null; then
echo "gunzip 未安装,正在安装..."
if command -v apt-get &> /dev/null; then
if command -v apt-get &>/dev/null; then
sudo apt-get update && sudo apt-get install -y gzip
elif command -v yum &> /dev/null; then
elif command -v yum &>/dev/null; then
sudo yum install -y gzip
elif command -v brew &> /dev/null; then
elif command -v brew &>/dev/null; then
brew install gzip
else
echo "错误: 无法安装 gunzip,请手动安装 gzip 工具"
@@ -18,57 +37,52 @@ function check_gunzip() {
fi
}
function install_mihomo() {
local os_arch=$(get_os_arch)
install_mihomo() {
local os_arch
os_arch=$(get_os_arch)
local base_url="https://oss-default.yumee.top/bin/mihomo"
local url=""
case $os_arch in
"darwin-amd64"|"darwin-arm64"|"linux-amd64"|"linux-arm64")
url="${base_url}/mihomo-${os_arch}.gz"
echo "正在为 ${os_arch} 平台安装 mihomo..."
;;
*)
echo "错误: 不支持的平台 ${os_arch}"
exit 1
;;
"darwin-amd64" | "darwin-arm64" | "linux-amd64" | "linux-arm64")
url="${base_url}/mihomo-${os_arch}.gz"
echo "正在为 ${os_arch} 平台安装 mihomo..."
;;
*)
echo "错误: 不支持的平台 ${os_arch}"
exit 1
;;
esac
# 检查 gunzip 命令
check_gunzip
# 创建临时目录
local temp_dir=$(mktemp -d)
local temp_dir
temp_dir=$(mktemp -d)
local temp_file="${temp_dir}/mihomo.gz"
# 下载文件
echo "正在从 ${url} 下载..."
if ! curl -L -o "${temp_file}" "${url}"; then
echo "错误: 下载失败"
rm -rf "${temp_dir}"
exit 1
fi
# 解压文件
echo "正在解压..."
if ! gunzip "${temp_file}"; then
echo "错误: 解压失败"
rm -rf "${temp_dir}"
exit 1
fi
# 移动到 /usr/local/bin 并设置执行权限
local binary="${temp_dir}/mihomo"
echo "正在安装到 /usr/local/bin/mihomo..."
sudo mv "${binary}" /usr/local/bin/mihomo
sudo chmod +x /usr/local/bin/mihomo
# 清理临时文件
rm -rf "${temp_dir}"
echo "mihomo 安装完成!"
echo "版本信息:"
/usr/local/bin/mihomo version || echo "mihomo 已安装到 /usr/local/bin/mihomo"
}
install_mihomo
install_mihomo
+31 -24
View File
@@ -1,41 +1,55 @@
#!/bin/bash
# 安装 mise 并链接 dotfile 配置、安装 config.toml 中的工具
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: mise-install
1. 若未安装则通过官方脚本安装 mise
2. 链接 ~/.dotfile/mise/config.toml
3. 执行 mise install 安装配置中的工具
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -e
# 设置颜色
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
NC='\033[0m'
# 检查是否已安装 mise
if ! command -v mise &> /dev/null
then
if ! command -v mise &>/dev/null; then
echo -e "${YELLOW}mise 未安装. 正在安装 mise...${NC}"
# 安装 mise(官方安装脚本会自动配置 shell)
curl https://mise.run | sh
# 重新加载当前 shell 环境
export PATH="$HOME/.local/bin:$PATH"
# 如果安装脚本没有自动配置,手动配置 fish shell(如果存在)
if [ -f ~/.config/fish/config.fish ]; then
if ! grep -q "mise activate" ~/.config/fish/config.fish; then
echo -e "${YELLOW}正在为 fish shell 配置 mise...${NC}"
echo '' >> ~/.config/fish/config.fish
echo '# mise (formerly rtx)' >> ~/.config/fish/config.fish
echo 'mise activate fish | source' >> ~/.config/fish/config.fish
{
echo ''
echo '# mise (formerly rtx)'
echo 'mise activate fish | source'
} >>~/.config/fish/config.fish
echo -e "${GREEN}已将 mise 添加到 ~/.config/fish/config.fish${NC}"
fi
fi
echo -e "${GREEN}mise 安装完成${NC}"
else
echo -e "${GREEN}mise 已安装${NC}"
mise --version
fi
# 链接 dotfile 中的 mise 配置
MISE_CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/mise"
DOTFILE_MISE_CONFIG="$HOME/.dotfile/mise/config.toml"
mkdir -p "$MISE_CONFIG_DIR"
@@ -49,22 +63,15 @@ if [ -f "$DOTFILE_MISE_CONFIG" ]; then
mise trust "$DOTFILE_MISE_CONFIG" 2>/dev/null || true
fi
# 安装配置中的工具
if command -v mise &> /dev/null && [ -f "$MISE_CONFIG_DIR/config.toml" ]; then
if command -v mise &>/dev/null && [ -f "$MISE_CONFIG_DIR/config.toml" ]; then
echo -e "${YELLOW}正在安装 mise 工具...${NC}"
mise install
echo -e "${GREEN}mise 工具安装完成${NC}"
fi
# 验证安装
if command -v mise &> /dev/null
then
if command -v mise &>/dev/null; then
echo -e "${GREEN}mise 安装成功!${NC}"
echo -e "${YELLOW}提示: 如果 mise 命令不可用,请重新打开终端或运行:${NC}"
echo -e "${GREEN}export PATH=\"\$HOME/.local/bin:\$PATH\"${NC}"
echo -e "${YELLOW}或者重新加载 shell 配置文件${NC}"
else
echo -e "${RED}mise 安装失败,请检查错误信息${NC}"
exit 1
fi
+9 -5
View File
@@ -1,7 +1,9 @@
#!/bin/bash
# 为指定用户配置某命令的免密 sudo(写入 /etc/sudoers.d/)
# 用法: sudo nosudo <user> <command>
# 示例: sudo nosudo xuser docker
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
set -euo pipefail
@@ -21,12 +23,14 @@ usage() {
- 仅允许免密执行解析到的那个可执行文件路径(含子命令参数仍受 sudo 规则约束)
- 对 docker,更推荐: sudo docker-group <user>(无需 sudo 即可用 docker)
- 删除规则: sudo rm /etc/sudoers.d/nosudo-<user>-<name>
选项:
-h, --help 显示此帮助
EOF
exit 1
}
[[ "${1:-}" == "-h" || "${1:-}" == "--help" ]] && usage
[[ $# -eq 2 ]] || usage
dotfile_help_requested "${1:-}" && dotfile_show_help
[[ $# -eq 2 ]] || { usage; exit 1; }
if [[ $EUID -ne 0 ]]; then
echo "错误: 请使用 sudo 运行,例如: sudo $0 $*"
+21 -10
View File
@@ -1,38 +1,49 @@
#!/bin/bash
# 将 Neovim 配置目录链接到 dotfile/nvim
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: nvim-init
将 ~/.config/nvim 软链接到 ~/.dotfile/nvim。
已有配置会备份为 nvim.backup.<时间戳>。
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
# 定义变量
NVIM_CONFIG_DIR="$HOME/.config/nvim"
YOUR_CUSTOM_CONFIG_DIR="$HOME/.dotfile/nvim" # 请替换为您的自定义配置目录路径
YOUR_CUSTOM_CONFIG_DIR="$HOME/.dotfile/nvim"
# 检查软链接是否已经存在并指向正确的目录
if [ -L "$NVIM_CONFIG_DIR" ] && [ "$(readlink -f "$NVIM_CONFIG_DIR")" = "$(readlink -f "$YOUR_CUSTOM_CONFIG_DIR")" ]; then
echo "软链接已经存在并指向正确的目录。无需进行任何操作。"
exit 0
fi
# 检查是否存在现有的 Neovim 配置
if [ -e "$NVIM_CONFIG_DIR" ]; then
echo "检测到现有的 Neovim 配置。"
# 如果是目录或常规文件,创建备份
if [ -d "$NVIM_CONFIG_DIR" ] || [ -f "$NVIM_CONFIG_DIR" ]; then
BACKUP_DIR="$NVIM_CONFIG_DIR.backup.$(date +%Y%m%d%H%M%S)"
mv "$NVIM_CONFIG_DIR" "$BACKUP_DIR"
echo "已将现有配置备份到 $BACKUP_DIR"
else
# 如果是其他类型的文件(如损坏的软链接),直接删除
rm "$NVIM_CONFIG_DIR"
echo "已删除现有的无效配置。"
fi
fi
# 创建软链接
ln -s "$YOUR_CUSTOM_CONFIG_DIR" "$NVIM_CONFIG_DIR"
# 检查软链接是否创建成功
if [ -L "$NVIM_CONFIG_DIR" ] && [ "$(readlink -f "$NVIM_CONFIG_DIR")" = "$(readlink -f "$YOUR_CUSTOM_CONFIG_DIR")" ]; then
echo "软链接创建成功。Neovim 现在将使用您的自定义配置。"
else
echo "创建软链接时出错。请检查路径和权限。"
exit 1
fi
+30 -18
View File
@@ -1,8 +1,28 @@
#!/bin/bash
# 从 GitHub Release 安装 Neovim 到 /usr/local/nvim
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: nvim-install
按当前平台下载 Neovim v0.12.2 预编译包,安装到 /usr/local/nvim,
并链接 nvim/vim 到 /usr/local/bin。
支持: macOS x86_64/arm64, Linux x86_64/arm64
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -e
# install neovim
os_arch=$(uname -s)-$(uname -m)
ver=v0.12.2
@@ -10,57 +30,49 @@ case $os_arch in
"Darwin-x86_64")
cd /tmp
rm -rf nvim-macos-x86_64.tar.gz
wget https://github.com/neovim/neovim/releases/download/$ver/nvim-macos-x86_64.tar.gz
wget "https://github.com/neovim/neovim/releases/download/$ver/nvim-macos-x86_64.tar.gz"
tar zxf nvim-macos-x86_64.tar.gz
sudo mv -f /usr/local/nvim /usr/local/nvim-bak
sudo mv -f /usr/local/nvim /usr/local/nvim-bak 2>/dev/null || true
sudo mv nvim-macos-x86_64 /usr/local/nvim
sudo ln -sf /usr/local/nvim/bin/nvim /usr/local/bin/vim
sudo ln -sf /usr/local/nvim/bin/nvim /usr/local/bin/nvim
echo ""
vim -v
;;
"Darwin-arm64" | "Darwin-aarch64")
cd /tmp
rm -rf nvim-macos-arm64.tar.gz
wget https://github.com/neovim/neovim/releases/download/$ver/nvim-macos-arm64.tar.gz
wget "https://github.com/neovim/neovim/releases/download/$ver/nvim-macos-arm64.tar.gz"
tar zxf nvim-macos-arm64.tar.gz
[ -e /usr/local/nvim ] && sudo mv -f /usr/local/nvim /usr/local/nvim-bak
sudo mv nvim-macos-arm64 /usr/local/nvim
sudo ln -sf /usr/local/nvim/bin/nvim /usr/local/bin/vim
sudo ln -sf /usr/local/nvim/bin/nvim /usr/local/bin/nvim
echo ""
vim -v
;;
"Linux-x86_64")
cd /tmp
rm -rf nvim-linux64.tar.gz
wget https://github.com/neovim/neovim/releases/download/$ver/nvim-linux-x86_64.tar.gz
rm -rf nvim-linux-x86_64.tar.gz
wget "https://github.com/neovim/neovim/releases/download/$ver/nvim-linux-x86_64.tar.gz"
tar zxf nvim-linux-x86_64.tar.gz
[ -e /usr/local/nvim ] && sudo mv -f /usr/local/nvim /usr/local/nvim-bak
sudo mv nvim-linux-x86_64 /usr/local/nvim
sudo ln -sf /usr/local/nvim/bin/nvim /usr/local/bin/vim
sudo ln -sf /usr/local/nvim/bin/nvim /usr/local/bin/nvim
echo ""
vim -v
;;
"Linux-arm64" | "Linux-aarch64")
cd /tmp
rm -rf nvim-linux64.tar.gz
wget https://github.com/neovim/neovim/releases/download/$ver/nvim-linux-arm64.tar.gz
tar zxf nvim-linux64.tar.gz
rm -rf nvim-linux-arm64.tar.gz
wget "https://github.com/neovim/neovim/releases/download/$ver/nvim-linux-arm64.tar.gz"
tar zxf nvim-linux-arm64.tar.gz
[ -e /usr/local/nvim ] && sudo mv -f /usr/local/nvim /usr/local/nvim-bak
sudo mv nvim-linux64 /usr/local/nvim
sudo mv nvim-linux-arm64 /usr/local/nvim
sudo ln -sf /usr/local/nvim/bin/nvim /usr/local/bin/vim
sudo ln -sf /usr/local/nvim/bin/nvim /usr/local/bin/nvim
echo ""
vim -v
;;
*)
echo "不支持的平台: $os_arch" >&2
exit 1
;;
esac
# if has error "no c compile found"
# sudo apt install build-essential
+27 -5
View File
@@ -1,9 +1,31 @@
#!/bin/bash
# 安装 fnm(Node 版本管理)并 reload fish 配置
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: nvm-install
通过 fnm 官方安装脚本安装 Fast Node Manager,并执行 ff reload。
选项:
-h, --help 显示此帮助
说明: 本仓库 fish 配置中 nvm 别名指向 fnm。
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -euo pipefail
# https://github.com/Schniz/fnm
curl -fsSL https://fnm.vercel.app/install | bash
ff reload
# after install node
# corepack enable pnpm
if command -v ff &>/dev/null; then
ff reload
elif command -v fish &>/dev/null; then
fish -c "source ~/.config/fish/config.fish"
fi
+28 -15
View File
@@ -1,38 +1,51 @@
#!/bin/bash
# 安装 pyenv 并配置 Python 3.11.10 及常用包
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: python-install
1. 若未安装则安装 pyenv
2. 安装 Python 3.11.10 并设为 global
3. 升级 pip 并安装 ipython/jupyter 等常用包
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -e
# 设置颜色
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # No Color
NC='\033[0m'
# 检查是否已安装 pyenv
if ! command -v pyenv &> /dev/null
then
if ! command -v pyenv &>/dev/null; then
echo -e "${RED}pyenv 未安装. 正在安装 pyenv...${NC}"
# 安装 pyenv
curl https://pyenv.run | bash
source ~/.config/fish/config.fish
if [ -f ~/.config/fish/config.fish ]; then
# shellcheck disable=SC1090
source ~/.config/fish/config.fish 2>/dev/null || true
fi
else
echo -e "${GREEN}pyenv 已安装${NC}"
fi
# 询问用户想安装的 Python 版本
python_version=3.11.10
# 安装指定版本的 Python
echo -e "${GREEN}正在安装 Python $python_version...${NC}"
pyenv install $python_version
pyenv install "$python_version"
pyenv global "$python_version"
# 设置全局 Python 版本
pyenv global $python_version
# 验证安装
installed_version=$(python --version)
echo -e "${GREEN}Python 安装完成. 当前版本: $installed_version${NC}"
# 安装一些常用的 Python 包
echo -e "${GREEN}正在安装一些常用的 Python 包...${NC}"
pip install --upgrade pip
pip install ipython jupyter notebook pandas numpy matplotlib scikit-learn
+26 -19
View File
@@ -1,12 +1,29 @@
#!/bin/bash
# ICMP/TCP 扫描本网段或指定网段的在线主机与开放端口
# 用法:
# ./scan-ip.sh # ICMP 扫描本网段在线 IP
# ./scan-ip.sh 10.0.0 # ICMP 扫描指定网段(10.0.0.1-254)
# ./scan-ip.sh 22 # 扫描本网段中 22 端口开放的 IP
# ./scan-ip.sh 80,443,8080 # 扫描本网段中任一指定端口开放的 IP
# ./scan-ip.sh 22 10.0.0 # 指定网段前缀 + 端口(顺序不限)
# ./scan-ip.sh 10.0.0 22 # 同上
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: scan-ip [端口或网段参数...]
扫描局域网主机:
无参数 ICMP 扫描本网段 .1-.254
10.0.0 扫描指定网段前缀
22 扫描本网段 TCP 22 端口
80,443,8080 扫描多个端口(任一开放即显示)
22 10.0.0 指定网段 + 端口(顺序不限)
选项:
-h, --help 显示此帮助
依赖: ping;端口模式需要 nc (netcat)。
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
TIMEOUT=1
@@ -31,8 +48,7 @@ fi
if [ -n "$1" ] && [ -z "$PORT_SPEC" ] && [ -z "$PREFIX_ARG" ]; then
echo "错误: 无法识别参数: $1"
echo "端口支持: 单端口(22) / 列表(80,443) / 范围(8000-8100)"
echo "网段支持: 前缀(10.0.0 或 192.168.1.0)"
usage
exit 1
fi
@@ -52,7 +68,6 @@ else
PREFIX="${LOCAL_IP%.*}"
fi
# 解析端口参数 -> PORTS 数组
PORTS=()
if [ -n "$PORT_SPEC" ]; then
if [[ "$PORT_SPEC" =~ ^[0-9]+$ ]]; then
@@ -68,7 +83,6 @@ if [ -n "$PORT_SPEC" ]; then
IFS=',' read -ra PORTS <<<"$PORT_SPEC"
else
echo "错误: 无效的端口格式: $PORT_SPEC"
echo "支持: 单端口(22) / 列表(80,443) / 范围(8000-8100)"
exit 1
fi
fi
@@ -81,10 +95,7 @@ else
fi
echo "------------------------------------------------------"
# ---------- 模式一:ICMP 在线扫描(无端口参数) ----------
if [ ${#PORTS[@]} -eq 0 ]; then
# macOS: -W 单位毫秒,-S 绑定源 IP
# Linux: -W 单位秒, -I 绑定源 IP
if [ "$(uname -s)" = "Darwin" ]; then
for i in $(seq 1 254); do
ping -c 1 -W 1000 -S "$LOCAL_IP" "$PREFIX.$i" >/dev/null 2>&1 && echo "$PREFIX.$i 在线" &
@@ -100,15 +111,11 @@ if [ ${#PORTS[@]} -eq 0 ]; then
exit 0
fi
# ---------- 模式二:TCP 端口扫描 ----------
if ! command -v nc &>/dev/null; then
echo "错误: 找不到 nc (netcat),请先安装:"
echo " macOS: brew install netcat"
echo " Debian/Ubuntu: sudo apt-get install netcat-openbsd"
echo "错误: 找不到 nc (netcat)"
exit 1
fi
# nc 在不同实现里 -z/-w 行为基本一致;用 -G 在 macOS 上控制连接超时更准
NC_OPTS=(-z -w "$TIMEOUT")
if [ "$(uname -s)" = "Darwin" ]; then
NC_OPTS+=(-G "$TIMEOUT")
+36 -40
View File
@@ -1,25 +1,42 @@
#!/bin/bash
# 对指定 IP 进行 TCP 端口扫描
# 端口扫描脚本
# 用法: ./scan-port.sh <IP地址> [端口范围]
# 示例: ./scan-port.sh 192.168.1.1
# 示例: ./scan-port.sh 192.168.1.1 80,443,8080
# 示例: ./scan-port.sh 192.168.1.1 1-1000
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: scan-port <IP> [端口范围]
扫描目标 IP 的 TCP 端口(使用 nc)。
参数:
IP 目标 IPv4 地址(必填)
端口范围 可选。默认扫描常用端口列表。
支持: 80,443,8080 或 1-1000
选项:
-h, --help 显示此帮助
示例:
scan-port 192.168.1.1
scan-port 192.168.1.1 22,80,443
scan-port 192.168.1.1 1-1000
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
# 检查是否提供了 IP 地址参数
if [ -z "$1" ]; then
echo "错误: 请提供要扫描的 IP 地址"
echo "用法: $0 <IP地址> [端口范围]"
echo "示例: $0 192.168.1.1"
echo "示例: $0 192.168.1.1 80,443,8080"
echo "示例: $0 192.168.1.1 1-1000"
echo "错误: 请提供要扫描的 IP 地址" >&2
usage
exit 1
fi
TARGET_IP="$1"
TIMEOUT=1 # 连接超时时间(秒)
TIMEOUT=1
# 验证 IP 地址格式(简单验证)
if ! [[ "$TARGET_IP" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
echo "错误: 无效的 IP 地址格式: $TARGET_IP"
exit 1
@@ -29,45 +46,33 @@ echo "=========================================="
echo "正在扫描 IP: $TARGET_IP"
echo "=========================================="
# 检查是否有 nc (netcat) 命令
if ! command -v nc &>/dev/null; then
echo "错误: 找不到 nc (netcat) 命令。"
echo "请安装 netcat:"
echo " macOS: brew install netcat"
echo " Linux: sudo apt-get install netcat 或 sudo yum install nc"
exit 1
fi
# 确定要扫描的端口
if [ -z "$2" ]; then
# 如果没有指定端口,扫描常用端口
PORTS=(21 22 23 25 53 80 110 111 135 139 143 443 445 993 995 1723 3306 3389 5432 5900 8080 8443)
echo "使用默认常用端口列表"
else
# 解析端口参数
PORT_SPEC="$2"
# 检查是否是范围格式 (例如: 1-1000)
if [[ "$PORT_SPEC" =~ ^[0-9]+-[0-9]+$ ]]; then
START_PORT=$(echo "$PORT_SPEC" | cut -d'-' -f1)
END_PORT=$(echo "$PORT_SPEC" | cut -d'-' -f2)
if [ "$START_PORT" -gt "$END_PORT" ]; then
echo "错误: 起始端口 ($START_PORT) 不能大于结束端口 ($END_PORT)"
exit 1
fi
PORTS=($(seq "$START_PORT" "$END_PORT"))
echo "扫描端口范围: $START_PORT-$END_PORT (共 $((END_PORT - START_PORT + 1)) 个端口)"
# 检查是否是逗号分隔的端口列表 (例如: 80,443,8080)
echo "扫描端口范围: $START_PORT-$END_PORT"
elif [[ "$PORT_SPEC" =~ ^[0-9,]+$ ]]; then
IFS=',' read -ra PORTS <<< "$PORT_SPEC"
IFS=',' read -ra PORTS <<<"$PORT_SPEC"
echo "扫描指定端口: $PORT_SPEC"
else
echo "错误: 无效的端口格式: $PORT_SPEC"
echo "支持的格式:"
echo " - 逗号分隔: 80,443,8080"
echo " - 范围: 1-1000"
exit 1
fi
fi
@@ -75,20 +80,14 @@ fi
echo "超时设置: ${TIMEOUT}秒"
echo "------------------------------------------------------"
# 统计变量
OPEN_PORTS=()
CLOSED_COUNT=0
TOTAL_PORTS=${#PORTS[@]}
# 扫描端口函数
scan_port() {
local port=$1
local ip=$2
# 使用 nc 扫描端口
# -z: 只扫描,不发送数据
# -v: 详细输出
# -w: 超时时间
if nc -z -v -w "$TIMEOUT" "$ip" "$port" 2>&1 | grep -q "succeeded\|open"; then
echo "✅ 端口 $port: 开放"
return 0
@@ -97,7 +96,6 @@ scan_port() {
fi
}
# 并行扫描端口(使用后台任务)
for port in "${PORTS[@]}"; do
if scan_port "$port" "$TARGET_IP"; then
OPEN_PORTS+=("$port")
@@ -106,7 +104,6 @@ for port in "${PORTS[@]}"; do
fi
done
# 等待所有后台任务完成
wait
echo "------------------------------------------------------"
@@ -128,4 +125,3 @@ else
fi
echo "=========================================="
+29 -8
View File
@@ -1,20 +1,41 @@
#/bin/bash
#!/bin/bash
# 链接 tmux 配置并安装 TPM 插件
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: tmux-init
1. 将 ~/.tmux.conf 链接到 ~/.dotfile/tmux/.tmux.conf
2. 克隆 tpm 到 ~/.tmux/plugins/tpm(若不存在)
3. 安装插件并 reload tmux 配置
选项:
-h, --help 显示此帮助
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -euo pipefail
echo 'Init tmux config'
src=$HOME/.tmux.conf
if [ -e $src ]; then
mv $src $src.bak
if [ -e "$src" ]; then
mv "$src" "$src.bak"
fi
ln -s $HOME/.dotfile/tmux/.tmux.conf $src
ln -s "$HOME/.dotfile/tmux/.tmux.conf" "$src"
echo 'Install tpm'
if [ ! -e ~/.tmux/plugins/tpm ]; then
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
fi
echo 'Install tmux plugin by tpm'
$HOME/.tmux/plugins/tpm/bin/install_plugins
"$HOME/.tmux/plugins/tpm/bin/install_plugins"
echo 'Reload tmux'
tmux source ~/.tmux.conf
tmux source ~/.tmux.conf
+24 -3
View File
@@ -1,6 +1,28 @@
#!/bin/bash
# 切换 CN_REGION 环境变量
# cn ↔ intl 切换
# 切换 CN_REGION 环境变量(国内/国外镜像与安装源)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: toggle-region
在当前 shell 中切换 CN_REGION:
1 -> 0 国内 -> 国外
0/未设置 -> 1 国外 -> 国内
影响依赖 CN_REGION 的安装脚本(如 docker-install)。
选项:
-h, --help 显示此帮助
说明: 仅影响当前 shell 会话;持久化请写入 fish/zsh 配置。
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
if [ "$CN_REGION" = "1" ]; then
export CN_REGION=0
@@ -9,4 +31,3 @@ else
export CN_REGION=1
echo "[INFO] Region switched to: 1 (国内)"
fi
+34 -11
View File
@@ -1,4 +1,27 @@
#!/bin/bash
# 链接 zshrc、安装 Oh My Zsh,并将默认 shell 设为 zsh
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "$SCRIPT_DIR/common/help.sh"
usage() {
cat <<'EOF'
用法: zsh-init
1. 将 ~/.zshrc 链接到 ~/.dotfile/zsh/.zshrc
2. 若未安装则安装 Oh My Zsh(--unattended --keep-zshrc)
3. 将默认登录 shell 设为 zsh
选项:
-h, --help 显示此帮助
本机额外配置可写入 ~/.zshrc.local。
EOF
}
dotfile_help_requested "${1:-}" && dotfile_show_help
set -euo pipefail
DOTFILE="${DOTFILE:-$HOME/.dotfile}"
@@ -7,33 +30,33 @@ ZSHRC_HOME="$HOME/.zshrc"
echo "Link zshrc"
if [[ -f "$ZSHRC_HOME" && ! -L "$ZSHRC_HOME" ]]; then
mv "$ZSHRC_HOME" "$ZSHRC_HOME.bak"
echo " 已备份原文件 -> $ZSHRC_HOME.bak"
mv "$ZSHRC_HOME" "$ZSHRC_HOME.bak"
echo " 已备份原文件 -> $ZSHRC_HOME.bak"
fi
ln -sf "$ZSHRC_REPO" "$ZSHRC_HOME"
echo " $ZSHRC_HOME -> $ZSHRC_REPO"
if [[ ! -d "$HOME/.oh-my-zsh" ]]; then
echo "安装 Oh My Zsh(--unattended:安装脚本内不改 shell、不自动进 zsh;--keep-zshrc:保留已链接的 .zshrc)…"
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended --keep-zshrc
echo "安装 Oh My Zsh…"
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended --keep-zshrc
else
echo "Oh My Zsh 已存在,跳过安装 (~/.oh-my-zsh)"
echo "Oh My Zsh 已存在,跳过安装 (~/.oh-my-zsh)"
fi
echo ""
echo "将默认登录 shell 设为 zsh"
zshpath="$(command -v zsh)"
if [[ -z "$zshpath" || ! -x "$zshpath" ]]; then
echo "错误: 找不到可执行的 zsh,请先安装 zsh。" >&2
exit 1
echo "错误: 找不到可执行的 zsh,请先安装 zsh。" >&2
exit 1
fi
if grep -qxF "$zshpath" /etc/shells 2>/dev/null; then
echo " $zshpath 已在 /etc/shells 中"
echo " $zshpath 已在 /etc/shells 中"
else
echo "$zshpath" | sudo tee -a /etc/shells
echo "$zshpath" | sudo tee -a /etc/shells
fi
chsh -s "$zshpath"
echo ""
echo "完成。当前仓库的 .zshrc 已启用 z 插件(Oh My Zsh plugins/z),默认 shell 已改为: $zshpath"
echo "请重新登录或新开终端后生效。本机额外配置可写入 ~/.zshrc.local(不会被链接覆盖)。"
echo "完成。默认 shell 已改为: $zshpath"
echo "请重新登录或新开终端后生效。"