我在终端里待时间可能比在浏览器里还多。有些事情在命令行里就是快。

这篇文章记录我目前在用工具链。不是教程,是我实际在用配置和习惯。你可能会发现一些地方可以借鉴,也可能觉得某些选择很奇怪。都正常,工具是长在手上。

tmux:终端里窗口管理器

我以前不用 tmux。觉得开多个终端窗口就行了,为什么要在一个终端里再套一层。

后来同时跑任务多了:ssh 连服务器、本地开发服务器、数据库客户端、git 操作、日志查看。窗口切来切去,找不到哪个是哪个。

tmux 解决的问题是:把多个会话装进一个终端窗口

我的 tmux 配置

我用的是 oh-my-tmux 作为基础配置,然后改了几处。

~/.tmux.conf.local 里我改了这些:

# ~/.tmux.conf.local
# 改用 Ctrl+a 作为前缀键,Ctrl+b 太别扭
set-option -g prefix C-a
unbind-key C-b
bind-key C-a send-prefix

# 鼠标支持(选文本、滚屏)
set -g mouse on

# 窗口编号从 1 开始,0 在左边太远
set -g base-index 1
setw -g pane-base-index 1

# 更长的历史记录
set -g history-limit 10000

# 分割面板的快捷键(模仿 vim)
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"

-c "#{pane_current_path}" 这个很重要。默认情况下,新分割面板会停留在用户目录,而不是当前目录。加上这个,新面板继承当前路径。

我常用操作

我的工作流一般是这样:一个 tmux 会话对应一个项目。

# 创建或重新连接项目会话
tmux new-session -s myproject -d  # 后台创建
tmux attach -t myproject          # 连接

# 或者直接:如果会话存在就连接,不存在就创建
tmux attach -t myproject || tmux new -s myproject

我在用快捷键组合:

  • Ctrl+a c — 创建新窗口
  • Ctrl+a 1-9 — 切换窗口
  • Ctrl+a % — 水平分割(我改成了 |,更好记)
  • Ctrl+a " — 垂直分割(我改成了 -
  • Ctrl+a 方向键 — 切换面板
  • Ctrl+a z — 最大化/恢复当前面板(临时需要大视野时用)
  • Ctrl+a [ — 进入复制模式,可以用鼠标滚屏

有一个操作我一开始不习惯:detach 之后会话还在跑。我以前会开着终端不关,现在直接 Ctrl+a d 退出,第二天连回来,一切都在。

zsh 和 oh-my-zsh

我用 zsh 不是因为它比 bash 强多少,而是 oh-my-zsh 的插件生态省事。

我的 .zshrc 精简版

# ~/.zshrc
export ZSH="$HOME/.oh-my-zsh"

# 主题(我用的是 powerlevel10k,但这是另一个话题)
ZSH_THEME="robbyrussell"

# 我实际在用的插件
plugins=(
  git
  docker
  docker-compose
  node
  npm
  python
  zsh-autosuggestions
  zsh-syntax-highlighting
  fzf
)

source $ZSH/oh-my-zsh.sh

# 下面是我自己的配置

主题我用是简单 robbyrussell。之前用过 powerlevel10k,显示信息很多,但我觉得干扰也多。现在只要一个当前目录和 git 分支就够了。

两个插件值得单独说

zsh-autosuggestions:输入命令时,会根据历史记录灰色显示建议。按 接受建议。这个插件帮我节省了很多重复输入。

zsh-syntax-highlighting:命令输错会显示红色。在按回车之前就知道命令有没有问题。

这两个插件都可以通过 oh-my-zsh 安装:

# autosuggestions
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

# syntax-highlighting
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

fzf:模糊搜索改变了一切

fzf 是一个通用模糊搜索工具。它可以搜索文件、命令历史、进程、git 提交,几乎任何东西。

安装和初始配置

# 安装(macOS)
brew install fzf

# 安装(Linux)
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install

# Windows 可以用 scoop 或 chocolatey
scoop install fzf

安装时它会问你要不要添加按键绑定和补全,选是。

我每天都在用 fzf 操作

搜索文件

# Ctrl+t 触发(这是 fzf 默认的按键绑定)
# 在命令行里按 Ctrl+t,会弹出文件搜索
# 输入部分文件名,选中后按回车,路径会插入到命令行

搜索命令历史

# Ctrl+r 触发
# 输入关键词,搜索历史命令
# 我常用这个找回之前跑过的长命令

在 vim 里搜索文件(如果你用 vim):

" 在 .vimrc 里添加
set rtp+=~/.fzf
nnoremap <C-p> :Files<CR>

Ctrl+p 搜索项目里文件。比手动输入路径快。

fzf 结合其他工具

fzf 本身是搜索界面,真正强大是和别工具组合。

搜索 git 提交

git log --oneline | fzf --preview 'git show {+1}'

--preview 会在上方显示选中项详情。我第一次看到这个效果时,觉得命令行也可以很直观。

搜索进程并 kill

ps aux | fzf --multi | awk '{print $2}' | xargs kill -9

--multi 允许选多个。不过这个操作有风险,我一般只用 kill 的交互模式(kill <PID>),不用批量。

fd、rg 和其他现代化工具

这些工具共同点是:它们做了和原有工具一样事情,但更好用。

fd 替代 find

find 命令的语法我一直记不住。每次要用都得查。

# 查找所有 .js 文件
# 旧的 find 方式
find . -name "*.js"

# fd 方式
fd -e js

fd 默认会忽略 .gitignore 里的文件。这很好,我一般不想搜到 node_modules 里的东西。

常用参数:

fd                  # 列出所有文件(递归)
fd -e md            # 找所有 markdown 文件
fd -t f "readme"    # 找文件名包含 readme 的文件
fd -t d "src"       # 找目录
fd -H "config"      # 包含隐藏文件

rg(ripgrep)替代 grep

grep -r 搜代码很慢,而且常常搜到不该搜地方。

# 在代码里搜索 "function"
# grep 方式
grep -r "function" .

# rg 方式
rg "function"

rg 的特点:

  • 自动忽略 .gitignore 里的文件和目录
  • 自动识别 .rgignore(类似 .gitignore
  • 速度快(用多线程搜索)
  • 默认彩色输出,匹配部分高亮

我常用:

rg "TODO"           # 找代码里的 TODO
rg -i "error"       # 不区分大小写
rg -w "main"        # 全词匹配(不匹配 "maintask" 之类的)
rg --type js "import"  # 只在 js 文件里搜

--type 参数会自动识别文件类型。支持几百种语言,不用手动写 -e js -e ts -e jsx

bat 替代 cat

cat 只是把文件内容打印出来。bat 会加上语法高亮和行号。

bat README.md       # 带语法高亮的查看
bat -n file.js      # 显示行号
bat -A file.js      # 显示不可打印字符(调试时用)

我还把 bat 设为了 man 的分页器:

# ~/.zshrc
export MANPAGER="sh -c 'col -bx | bat -l man -p'"

现在 man 页面也有语法高亮了。

exa 替代 ls(或 eza)

exals 的现代化替代品,彩色输出、图标、git 状态集成。

exa --icons -l       # 列表形式,带图标
exa --icons -T       # 树形显示目录结构
exa --icons -l --git # 显示 git 状态

注意:exa 已经停止维护。它的分支 eza 在继续开发。

# 安装 eza
brew install eza     # macOS
scoop install eza    # Windows

我把 ls 别名到了 eza

alias ls="eza --icons"
alias ll="eza --icons -l"
alias tree="eza --icons -T"

alias 和函数技巧

alias 和函数是在减少重复输入。我以前不太用,觉得记 alias 比记原命令更麻烦。后来发现,alias 是用来记那些你频繁用命令的。

我的 alias 清单

# ~/.zshrc

# 目录跳转
alias ..="cd .."
alias ...="cd ../.."
alias ~="cd ~"

# 编辑器
alias v="vim"
alias c="code ."          # VS Code 打开当前目录

# git 缩写(这些 oh-my-zsh 的 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"

# docker(容器多了之后,这些很省事)
alias dps="docker ps"
alias dpsa="docker ps -a"
alias di="docker images"
alias dex="docker exec -it"

# 系统
alias h="history"
alias cl="clear"
alias path="echo $PATH | tr ':' '\n'"  # 查看 PATH,每行一个

函数比 alias 更灵活

alias 只能做简单替换。函数可以接受参数、做条件判断。

智能解压函数

# ~/.zshrc
extract() {
  if [ -f $1 ]; then
    case $1 in
      *.tar.bz2)   tar xjf $1     ;;
      *.tar.gz)    tar xzf $1     ;;
      *.bz2)       bunzip2 $1     ;;
      *.rar)       unrar e $1     ;;
      *.gz)        gunzip $1      ;;
      *.tar)       tar xf $1      ;;
      *.tbz2)      tar xjf $1     ;;
      *.tgz)       tar xzf $1     ;;
      *.zip)       unzip $1       ;;
      *.Z)         uncompress $1  ;;
      *.7z)        7z x $1        ;;
      *)           echo "'$1' 无法解压" ;;
    esac
  else
    echo "'$1' 不是有效文件"
  fi
}

不管什么压缩格式,都用一个命令:extract file.tar.gz

快速创建并进入目录

mkcd() {
  mkdir -p "$1" && cd "$1"
}

在 vim 里打开当前 git 项目的 root

vg() {
  local root=$(git rev-parse --show-toplevel 2>/dev/null)
  if [ -n "$root" ]; then
    vim "$root/$1"
  else
    vim "$1"
  fi
}

最常用快捷键组合

这些是我在终端里手不离操作。

tmux

  • Ctrl+a d — detach(退出但保持会话)
  • Ctrl+a c — 新建窗口
  • Ctrl+a n / p — 下一个/上一个窗口
  • Ctrl+a } — 交换面板位置

命令行编辑(在 zsh/bash 里都有效):

  • Ctrl+a — 光标移到行首
  • Ctrl+e — 光标移到行尾
  • Ctrl+w — 删除光标前一个单词
  • Ctrl+k — 删除光标到行尾
  • Ctrl+u — 删除行首到光标
  • Ctrl+r — 搜索历史(fzf 增强版)
  • Alt+b / Alt+f — 按单词后退/前进

fzf

  • Ctrl+t — 搜索文件,结果插入命令行
  • Alt+c — 搜索目录,直接 cd 过去
  • Tab — 多选模式

我一开始记不住这么多。选几个你每天都会用,练成肌肉记忆,再往下加。

踩过的坑

不要在 tmux 里嵌套 tmux。我在服务器上用 tmux,本地也用 tmux,按键冲突很痛苦。现在的做法是:本地用 tmux 管理窗口,连服务器时直接用 ssh,不在服务器 tmux 里操作。或者,如果必须用服务器 tmux,本地 tmux 用 Ctrl+a 作为前缀,服务器上用 Ctrl+b,区分开。

oh-my-zsh 插件不是越多越好。我以前装了一堆插件,启动变慢。现在只留实际在用。启动时间从 3 秒降到了不到 1 秒。可以用 time zsh -i -c exit 测试启动时间。

fzf 的预览功能会拖慢大文件搜索。如果搜索结果很多,--preview 可能会卡。这时候可以按 ? 查看帮助,或者暂时关掉预览(Ctrl+/ 切换)。

总结

这套工具链我迭代了几年。每次加新工具,都会问自己:它解决是什么问题?如果只是为了用而用,我会删掉。

工具是手段。如果现在配置让你在终端里觉得顺手,那就够了。不用追新,也不用什么都用。


相关资源

种下你的想法

在花园里留下一条评论,和这篇文章一起生长。

COMMENTS