#!/bin/bash # .bash_shell_enhancements - 常用Shell命令增强 # 版本:1.2.0 # --- 颜色定义 --- _H_RED="\033[0;31m" # 红色 _H_GREEN="\033[0;32m" # 绿色 _H_YELLOW="\033[0;33m" # 黄色 _H_BLUE="\033[0;34m" # 蓝色 _H_PURPLE="\033[0;35m" # 紫色 _H_CYAN="\033[0;36m" # 青色 _H_WHITE="\033[0;37m" # 白色 _H_NC="\033[0m" # 重置颜色 # --- 目录导航别名 --- # 简化的目录导航别名 alias ..='cd ..' alias .2='cd ../..' alias .3='cd ../../..' alias .4='cd ../../../..' alias .5='cd ../../../../..' # --- 文件列表别名 --- # exa替代ls(删除icons) if command -v exa >/dev/null 2>&1; then alias ls='exa' # 默认exa,不显示隐藏文件 alias ll='exa -l' # 显示详细信息 alias la='exa -la' # 包含隐藏文件 alias lt='exa -T' # 树状结构显示 alias lta='exa -Ta' # 树状结构显示所有文件 else alias ls='ls --color=auto' # 回退到ls alias ll='ls -l --color=auto' alias la='ls -la --color=auto' alias lt='find . -type d | sort | sed -e "s/[^-][^\/]*\// |/g" -e "s/|\([^ ]\)/|-\1/"' fi # --- 文本搜索别名 --- alias grep='grep --color=auto' alias fgrep='fgrep --color=auto' alias egrep='egrep --color=auto' # --- 磁盘和网络命令 --- # 磁盘空间可视化 if command -v duf >/dev/null 2>&1; then alias df='duf' else alias df='df -h' # 回退到普通df命令 fi # 目录大小分析 if command -v dust >/dev/null 2>&1; then alias du='dust' else alias du='du -h' # 回退到普通du命令 fi # --- 子命令化的网络端口扫描 --- ports() { local usage="${_H_BLUE}用法:${_H_NC} ports [子命令] ${_H_BLUE}网络端口查看命令:${_H_NC} tcp - 仅显示TCP端口 udp - 仅显示UDP端口 listen - 仅显示监听端口 all - 显示所有端口连接 (默认) help - 显示此帮助信息 " case "$1" in tcp) if command -v ss >/dev/null 2>&1; then ss -tlnp elif command -v netstat >/dev/null 2>&1; then netstat -tlnp else echo "无法检查TCP端口: ss和netstat均未安装" fi ;; udp) if command -v ss >/dev/null 2>&1; then ss -ulnp elif command -v netstat >/dev/null 2>&1; then netstat -ulnp else echo "无法检查UDP端口: ss和netstat均未安装" fi ;; listen) if command -v ss >/dev/null 2>&1; then ss -lnp elif command -v netstat >/dev/null 2>&1; then netstat -lnp else echo "无法检查监听端口: ss和netstat均未安装" fi ;; help|--help|-h) echo -e "$usage" ;; all|"") if command -v ss >/dev/null 2>&1; then ss -tulanp elif command -v netstat >/dev/null 2>&1; then netstat -tulanp elif command -v lsof >/dev/null 2>&1; then lsof -i else echo "无法检查端口: ss, netstat, lsof 均未安装" fi ;; *) echo -e "未知子命令: $1\n" echo -e "$usage" return 1 ;; esac } # --- IP缓存机制 --- # 公网IP检测器(带缓存) _IP_CACHE_FILE="/tmp/gip_cache" _IP_CACHE_TTL=300 # 5分钟缓存 # 获取IPv4函数 (原始) _get_ipv4() { local providers=("ifconfig.me" "ipinfo.io/ip" "icanhazip.com" "ipecho.net/plain") for provider in "${providers[@]}"; do local ip=$(curl -s -4 --connect-timeout 5 "$provider" 2>/dev/null) if [ -n "$ip" ]; then echo "$ip" return 0 fi done echo "无法获取公网IPv4地址" # 所有源都失败 return 1 } # 获取IPv6函数 (原始) _get_ipv6() { local providers=("ipv6.icanhazip.com" "ipv6.ifconfig.me" "ipv6.ident.me") for provider in "${providers[@]}"; do local ip=$(curl -s -6 --connect-timeout 5 "$provider" 2>/dev/null) if [ -n "$ip" ]; then echo "$ip" return 0 fi done echo "无法获取公网IPv6地址或网络不支持IPv6" # 所有源都失败 return 1 } # 缓存版IPv4获取 _get_ipv4_cached() { if [ -f "$_IP_CACHE_FILE.v4" ]; then local cache_time=$(stat -c %Y "$_IP_CACHE_FILE.v4" 2>/dev/null || echo 0) local current_time=$(date +%s) local age=$((current_time - cache_time)) if [ $age -lt $_IP_CACHE_TTL ]; then cat "$_IP_CACHE_FILE.v4" return 0 fi fi # 缓存过期或不存在,重新获取 local ip=$(_get_ipv4) echo "$ip" > "$_IP_CACHE_FILE.v4" echo "$ip" } # 缓存版IPv6获取 _get_ipv6_cached() { if [ -f "$_IP_CACHE_FILE.v6" ]; then local cache_time=$(stat -c %Y "$_IP_CACHE_FILE.v6" 2>/dev/null || echo 0) local current_time=$(date +%s) local age=$((current_time - cache_time)) if [ $age -lt $_IP_CACHE_TTL ]; then cat "$_IP_CACHE_FILE.v6" return 0 fi fi local ip=$(_get_ipv6) echo "$ip" > "$_IP_CACHE_FILE.v6" echo "$ip" } # 获取JSON格式的完整IP信息 _get_ip_json() { local providers=("ipinfo.io" "ifconfig.me/all.json") for provider in "${providers[@]}"; do local data=$(curl -s --connect-timeout 5 "$provider" 2>/dev/null) if [ -n "$data" ]; then echo "$data" return 0 fi done echo "无法获取IP详细信息" # 所有源都失败 return 1 } # --- 公网IP检测(子命令版) --- gip() { local usage="${_H_BLUE}用法:${_H_NC} gip [子命令] ${_H_BLUE}公网IP查询命令:${_H_NC} 4 - 获取IPv4地址 (默认) 6 - 获取IPv6地址 all - 同时显示IPv4和IPv6地址 json - 显示完整IP信息(JSON格式) help - 显示此帮助信息 " case "$1" in 4|"") echo -e "${_H_BLUE}IPv4:${_H_NC} $(_get_ipv4_cached)" ;; 6) echo -e "${_H_BLUE}IPv6:${_H_NC} $(_get_ipv6_cached)" ;; all) echo -e "${_H_BLUE}IPv4:${_H_NC} $(_get_ipv4_cached)" echo -e "${_H_BLUE}IPv6:${_H_NC} $(_get_ipv6_cached)" ;; json) echo "$(_get_ip_json)" ;; help|--help|-h) echo -e "$usage" ;; *) echo -e "未知子命令: $1\n" echo -e "$usage" return 1 ;; esac } # --- 其他网络别名 --- alias clr='clear' # 统一清屏命令 alias ping='ping -c 5' # 默认只ping 5次 # --- 系统管理命令 --- alias free="free -h" # 以易读格式显示内存使用 alias cpu="top -o %CPU -n 1 | head -n 15" # 显示CPU占用最高的进程 alias mem="top -o %MEM -n 1 | head -n 15" # 显示内存占用最高的进程 alias psg="ps aux | grep -v grep | grep -i" # 按名称搜索进程 # --- 系统信息(子命令版) --- sys() { local usage="${_H_BLUE}用法:${_H_NC} sys [子命令] ${_H_BLUE}系统信息命令:${_H_NC} info - 显示系统基本信息概览 (默认) disk - 显示磁盘使用情况 mem - 显示内存使用情况 cpu - 显示CPU信息和负载 net - 显示网络接口信息 users - 显示当前登录用户 ps - 显示进程资源占用排行 all - 显示所有系统信息 help - 显示此帮助信息 " case "$1" in info|"") echo -e "${_H_BLUE}系统信息概览:${_H_NC}" echo "$(date '+%Y-%m-%d %H:%M:%S')" echo "主机名: $(hostname)" echo "发行版: $(lsb_release -ds 2>/dev/null || cat /etc/*release 2>/dev/null | head -n1 || uname -om)" echo "内核版本: $(uname -r)" echo "运行时间: $(uptime -p)" echo "系统负载: $(uptime | awk -F'load average:' '{print $2}')" ;; disk) echo -e "${_H_BLUE}磁盘使用情况:${_H_NC}" df -h ;; mem) echo -e "${_H_BLUE}内存使用情况:${_H_NC}" free -h ;; cpu) echo -e "${_H_BLUE}CPU信息:${_H_NC}" echo "物理CPU数: $(grep -c "physical id" /proc/cpuinfo 2>/dev/null || echo "未知")" echo "CPU核心数: $(nproc --all 2>/dev/null || echo "未知")" echo "CPU型号: $(grep "model name" /proc/cpuinfo | head -1 | cut -d':' -f2- | sed 's/^[ \t]*//' 2>/dev/null || echo "未知")" echo "CPU负载: $(uptime | awk -F'load average:' '{print $2}')" ;; net) echo -e "${_H_BLUE}网络接口信息:${_H_NC}" ip -br addr ;; users) echo -e "${_H_BLUE}当前登录用户:${_H_NC}" who ;; ps) echo -e "${_H_BLUE}进程资源占用排行:${_H_NC}" echo -e "${_H_YELLOW}CPU占用最高的进程:${_H_NC}" ps aux --sort=-%cpu | head -6 echo echo -e "${_H_YELLOW}内存占用最高的进程:${_H_NC}" ps aux --sort=-%mem | head -6 ;; all) sys info echo sys disk echo sys mem echo sys cpu echo sys net echo sys users echo sys ps ;; help|--help|-h) echo -e "$usage" ;; *) echo -e "未知子命令: $1\n" echo -e "$usage" return 1 ;; esac } # 向后兼容性别名 alias sysinfo='sys info' # --- Git别名和命令 --- if command -v git >/dev/null 2>&1; then # 基本Git别名 alias gs="git status" alias ga="git add" alias gc="git commit" alias gp="git push" alias gl="git pull" alias gd="git diff" alias gco="git checkout" alias gb="git branch" alias glog="git log --oneline --graph --decorate" # Git增强命令 git_helper() { local usage="${_H_BLUE}用法:${_H_NC} g [子命令] ${_H_BLUE}Git增强命令:${_H_NC} s, status - git status a, add - git add c, commit - git commit p, push - git push l, pull - git pull d, diff - git diff co, checkout - git checkout b, branch - git branch log - 美化的git日志 sync - 同步当前分支(fetch+merge) undo - 撤销最后一次提交 clean - 清理本地仓库 help - 显示此帮助信息 " case "$1" in s|status) git status ;; a|add) shift git add "$@" ;; c|commit) shift git commit "$@" ;; p|push) shift git push "$@" ;; l|pull) shift git pull "$@" ;; d|diff) shift git diff "$@" ;; co|checkout) shift git checkout "$@" ;; b|branch) shift git branch "$@" ;; log) git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit ;; sync) local branch=$(git rev-parse --abbrev-ref HEAD) echo -e "${_H_BLUE}同步分支:${_H_NC} $branch" git fetch origin "$branch" && git merge "origin/$branch" ;; undo) git reset --soft HEAD^ echo -e "${_H_GREEN}已撤销最后一次提交,但保留更改${_H_NC}" ;; clean) git clean -fd git gc echo -e "${_H_GREEN}已清理仓库并优化${_H_NC}" ;; help|--help|-h|"") echo -e "$usage" ;; *) echo -e "未知子命令: $1\n" echo -e "$usage" return 1 ;; esac } # 使用g作为Git增强命令的别名 alias g='git_helper' fi # --- 文件操作增强命令 --- file() { local usage="${_H_BLUE}用法:${_H_NC} file [子命令] [参数] ${_H_BLUE}文件操作命令:${_H_NC} find <模式> - 按名称查找文件 text <模式> - 搜索文件内容 extract <文件> - 智能解压文件 newest [目录] - 显示最近修改的文件 largest [目录] - 显示最大的文件 help - 显示此帮助信息 " case "$1" in find) if [ -z "$2" ]; then echo "用法: file find <文件名模式>" return 1 fi if command -v fd >/dev/null 2>&1; then fd "$2" . else find . -type f -name "*$2*" 2>/dev/null fi ;; text) if [ -z "$2" ]; then echo "用法: file text <搜索内容>" return 1 fi if command -v rg >/dev/null 2>&1; then rg "$2" . else grep -r "$2" . fi ;; extract) if [ -z "$2" ]; then echo "用法: file extract <压缩文件>" return 1 fi if [ -f "$2" ]; then case "$2" in *.tar.bz2) tar xjf "$2" ;; *.tar.gz) tar xzf "$2" ;; *.bz2) bunzip2 "$2" ;; *.rar) unrar x "$2" ;; *.gz) gunzip "$2" ;; *.tar) tar xf "$2" ;; *.tbz2) tar xjf "$2" ;; *.tgz) tar xzf "$2" ;; *.zip) unzip "$2" ;; *.Z) uncompress "$2" ;; *.7z) 7z x "$2" ;; *) echo "'$2' 无法解压" ;; esac else echo "'$2' 不是有效的文件" fi ;; newest) local dir="${2:-.}" find "$dir" -type f -printf '%T@ %T+ %p\n' | sort -n | tail -10 | cut -f2- -d" " ;; largest) local dir="${2:-.}" find "$dir" -type f -printf '%s %p\n' | sort -nr | head -10 | \ awk '{suffix="KMGT"; for(i=0;$1>1024 && i < length(suffix);i++) $1/=1024; printf("%6.2f%s %s\n", $1, substr(suffix, i+1, 1), $2)}' ;; help|--help|-h|"") echo -e "$usage" ;; *) echo -e "未知子命令: $1\n" echo -e "$usage" return 1 ;; esac } # 向后兼容性别名 alias seek='file find' alias ffind='file text' alias extract='file extract' alias ff='file find' # 创建目录并进入 mkcd() { if [ -z "$1" ]; then echo "用法: mkcd <目录名>" return 1 fi mkdir -p "$@" && cd "${@: -1}" || return 1 } # --- 快速跳转标记 --- # 为常用目录创建书签 mark() { local usage="${_H_BLUE}用法:${_H_NC} mark [子命令] ${_H_BLUE}目录标记命令:${_H_NC} add <名称> - 将当前目录标记为<名称> go <名称> - 跳转到标记的目录 rm <名称> - 删除标记 ls - 列出所有标记 help - 显示此帮助信息 " # 确保书签目录存在 local MARKDIR="$HOME/.marks" mkdir -p "$MARKDIR" case "$1" in add) if [ -z "$2" ]; then echo "请提供标记名称" return 1 fi ln -s "$(pwd)" "$MARKDIR/$2" echo "已添加标记: $2 -> $(pwd)" ;; go) if [ -z "$2" ]; then echo "请提供标记名称" return 1 fi if [ -L "$MARKDIR/$2" ]; then cd "$(readlink "$MARKDIR/$2")" || return 1 else echo "标记不存在: $2" return 1 fi ;; rm) if [ -z "$2" ]; then echo "请提供标记名称" return 1 fi rm -f "$MARKDIR/$2" echo "已删除标记: $2" ;; ls) for mark in "$MARKDIR"/*; do if [ -L "$mark" ]; then local name=$(basename "$mark") local target=$(readlink "$mark") echo -e "${_H_BLUE}$name${_H_NC} -> $target" fi done ;; help|--help|-h|"") echo -e "$usage" ;; *) echo -e "未知子命令: $1\n" echo -e "$usage" return 1 ;; esac } # --- 帮助函数 (美化版) --- shell_help() { local usage="${_H_BLUE}Shell增强工具${_H_NC} - 常用命令集合 ${_H_BLUE}导航命令:${_H_NC} .. - 回到上一级目录 .2, .3 - 回到上两级或三级目录 .4, .5 - 回到更上层目录 mark add <名称> - 将当前目录标记为<名称> mark go <名称> - 跳转到标记的目录 mark ls - 列出所有标记 ${_H_BLUE}文件命令:${_H_NC} file find <模式> - 按名称查找文件 file text <模式> - 搜索文件内容 file extract <文件> - 智能解压文件 file newest [目录] - 显示最近修改的文件 file largest [目录] - 显示最大的文件 mkcd <目录名> - 创建并进入目录 ${_H_BLUE}系统命令:${_H_NC} sys info - 显示系统基本信息 sys disk - 显示磁盘使用情况 sys mem - 显示内存使用情况 sys cpu - 显示CPU信息 sys net - 显示网络接口信息 sys ps - 显示进程资源占用 sys all - 显示所有系统信息 ${_H_BLUE}网络命令:${_H_NC} gip [4|6|all|json] - 获取公网IP地址 ports [tcp|udp|listen|all] - 显示网络端口 ${_H_BLUE}Git命令:${_H_NC} g s, g status - 显示状态 g a, g add - 添加文件 g c, g commit - 提交更改 g p, g push - 推送更改 g l, g pull - 拉取更改 g log - 美化的提交日志 g sync - 同步当前分支 g undo - 撤销最后一次提交 ${_H_BLUE}基础别名:${_H_NC} ls, ll, la - 文件列表 df, du - 磁盘使用 free - 内存使用 grep, psg - 文本和进程搜索 clr - 清屏 " echo -e "$usage" } # 设置别名 alias help='shell_help' # --- 命令补全 --- # 为自定义函数添加补全 _mkcd_complete() { local cur="${COMP_WORDS[COMP_CWORD]}" _filedir -d } _gip_complete() { local cur="${COMP_WORDS[COMP_CWORD]}" local opts="4 6 all json help" COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) } _ports_complete() { local cur="${COMP_WORDS[COMP_CWORD]}" local opts="tcp udp listen all help" COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) } _sys_complete() { local cur="${COMP_WORDS[COMP_CWORD]}" local opts="info disk mem cpu net users ps all help" COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) } _git_helper_complete() { local cur="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD -eq 1 ]]; then local opts="s status a add c commit p push l pull d diff co checkout b branch log sync undo clean help" COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) else # 对于git子命令的参数,使用git自带的补全 local cmd="${COMP_WORDS[1]}" case "$cmd" in a|add|c|commit|p|push|l|pull|d|diff|co|checkout|b|branch) # 提取实际git命令 local gitcmd case "$cmd" in a) gitcmd="add" ;; c) gitcmd="commit" ;; p) gitcmd="push" ;; l) gitcmd="pull" ;; d) gitcmd="diff" ;; co) gitcmd="checkout" ;; b) gitcmd="branch" ;; *) gitcmd="$cmd" ;; esac # 构建新的COMP_WORDS和COMP_CWORD用于git补全 local words=("git" "$gitcmd") for ((i=2; i<${#COMP_WORDS[@]}; i++)); do words+=("${COMP_WORDS[i]}") done # 现在我们有了一个类似于"git xxx"的命令行 COMP_WORDS=("${words[@]}") COMP_CWORD=$((COMP_CWORD)) # 使用git的补全函数 _git ;; esac fi } _file_complete() { local cur="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD -eq 1 ]]; then local opts="find text extract newest largest help" COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) else local cmd="${COMP_WORDS[1]}" case "$cmd" in extract) COMPREPLY=( $(compgen -f -- "${cur}") ) ;; newest|largest) _filedir -d ;; esac fi } _mark_complete() { local cur="${COMP_WORDS[COMP_CWORD]}" local cmd="${COMP_WORDS[1]}" if [[ $COMP_CWORD -eq 1 ]]; then local opts="add go rm ls help" COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) elif [[ $COMP_CWORD -eq 2 && ("$cmd" == "go" || "$cmd" == "rm") ]]; then local marks=$(ls "$HOME/.marks/" 2>/dev/null) COMPREPLY=( $(compgen -W "${marks}" -- "${cur}") ) fi } # 注册补全 if type complete &>/dev/null; then complete -F _mkcd_complete mkcd complete -F _gip_complete gip complete -F _ports_complete ports complete -F _sys_complete sys complete -F _git_helper_complete g complete -F _file_complete file complete -F _mark_complete mark complete -c which complete -c command fi # 初始化提示 echo -e "${_H_GREEN}Shell增强工具已加载${_H_NC}" echo -e "输入 ${_H_BLUE}help${_H_NC} 查看可用命令"