美文网首页程序员
Linux命令行效率提升技巧与工具

Linux命令行效率提升技巧与工具

作者: gratonos | 来源:发表于2019-08-17 12:24 被阅读0次

    技巧

    以下技巧均适用于 bash ,其他类型的 shell 可能不一定能全部适用。

    快捷键模式

    默认情况下, shell 的快捷键为 emacs 模式,如: Ctrl-A / Ctrl-E 将光标移动到行 头 / 尾, Ctrl-F / Ctrl-B 将光标向 前 / 后 移动一个字符, Ctrl-P / Ctrl-N 选择 上 / 下 一条历史命令等。
    为了提升命令编辑效率,我们可以把快捷键设置为 vi 模式,之后我们就能使用 vi 的快捷键来编辑命令, shell 将像 vi 一样,可以在 normal 模式和 insert 模式之间切换。
    下面的设置将 shell 的快捷键设置为 vi 模式,并且还附带了一些辅助设置:

    set -o vi                          # 将 shell 快捷键设置为 vi 模式
    stty werase undef                  # 取消 Ctrl-W 绑定(向后删除一个单词,空格为单词分隔符)
    bind '\C-w:backward-kill-word'     # 重新绑定 Ctrl-W (向后删除一个单词,非字母 / 数字字符为单词分隔符)
    bind '\C-l:clear-screen'           # 绑定 Ctrl-L 到清屏功能
    bind '\C-f:forward-search-history' # 绑定 Ctrl-F 到向前查找历史命令功能(Ctrl-S 已绑定到暂停 shell 输出功能)
    

    定制命令行提示

    很多 LinuxServer 发行版的命令行提示默认比较简单,也没有颜色高亮,白(黄 / 绿)花花一片,我们输入的命令、命令的输出同样也是白(黄 / 绿)花花一片。当命令的输出很多时,我们用眼睛去识别哪部分是命令行提示、输入的命令或命令的输出会很费劲。
    下面的设置将命令行提示符设置为:绿色显示用户名和主机名、蓝色显示当前的绝对路径、紫色显示当前时间

    PS1='\[\033[01;32m\]\u@\h\[\033[00m\] \[\033[01;34m\]\w\[\033[00m\] \[\033[01;35m\]\t\[\033[00m\] \[\033[01;34m\]\$\[\033[00m\] '
    

    历史查找

    仅使用 上 / 下 方向键(通用)、k / jvi 模式)、Ctrl-P / Ctrl-Nemacs 模式)来翻找历史命令是很低效的,我们可以对历史命令进行增量搜索。
    Ctrl-R之后,输入要搜索的历史命令(命令的任何一部分都行,如命令名、参数等),这时将开始历史命令的向 增量搜索过程。此时,如果连续按 Ctrl-R ,那么将不断显示上一条匹配当前输入的历史命令。如果有根据 快捷键模式 部分的推荐配置绑定了 Ctrl-F 的话,那么按 Ctrl-F 将转为历史命令的向 增量搜索过程。
    找到自己想要的历史命令后,按 ESCvi 模式) / Ctrl-Gemacs 模式)退出搜索过程,继续编辑命令;也可以直接按 Enter 执行当前命令。

    别名

    使用命令行难免需要经常重复输入一些比较繁琐的命令,给这些繁琐的命令定义简单的别名,可以节省大量的时间。别名的另一个用途是重新定义命令的行为,比如给一些命令增加上默认的参数等。很多 Linux 发行版都定义了一些简单的别名,如下:

    alias cp='cp -i'
    alias rm='rm -i'
    alias mv='mv -i'
    

    这些别名可以防止我们不小心错误地删除或覆盖文件。另外,如果我们想绕过别名机制,直接使用原始命令,那么在命令前加上反斜杠 \ 即可,如下:

    \rm test.txt
    

    函数

    有时候我们可能想使用一条命令执行一系列操作,如果我们把这一系列操作定义为别名,会导致定义过于复杂,可读性比较差;也可能我们需要传一些参数给若干命令,使用定义别名的方式无法满足这一需求。这时候我们可以定义 shell 函数。下面是几个简单的例子,其中$1代表函数的第一个参数:

    mcd() { mkdir -p "$1" && cd "$1"; }
    cls() { cd "$1" && ls; }
    backup() { cp "$1"{,.bak}; }
    

    shell 函数的调用与执行普通命令的方式一样,如下:

    mcd test
    

    命令补全

    我们都知道输入命令时,可以按 Tab 补全命令、文件名等,但是可能不是所有人都知道, shell 的补全机制其实是设计为可扩展的。以 debian 系的发行版为例(其他发行版可能有出入),我们能在 /etc 目录下找到 bash_completion 文件 和 / 或 bash_completion.d 目录。它们是对命令补全的扩展配置,例如对 git 命令的子命令补全进行配置,这样我们就能用 Tab 补全 git 的子命令了。在 debian 系发行版中,安装 bash-completion 包,我们就能获得很多常用命令的扩展补全配置。

    历史展开

    shell 的历史展开涉及很多内容,这里只对历史参数展开方面的部分常用内容进行叙述,想做详细了解的朋友可以参考History Expansion
    shell 命令中,我们可以使用一些特殊的标识来表示 上一条 执行过的命令中的某一 个 / 些 参数,例如:

    • !*:所有参数
    • !^:第一个参数
    • !$:最后一个参数
    • !:n:第n个参数
    • !:a-b:第a个到第b个参数

    下面是一个实际例子,我们执行以下命令:

    ls t1 t2 t3 t4 t5
    ls !:2-4
    

    实际上执行的是:

    ls t1 t2 t3 t4 t5
    ls t2 t3 t4
    

    子进程

    shell 命令的执行默认是在当前 shell 进程中执行的,命令的执行能影响到当前的 shell 环境。如果我们不希望当前 shell 环境被影响,那么我们可以显式地指定命令在子进程中执行,方法就是用 小括号 将整条命令括起来,例如:

    (cd build && cmake ..)
    

    命令执行完成后, shell 的当前路径并不会发生变化。

    子进程的创建还有另外一种应用场景,即把一条命令的输出作为另外一条命令的 参数 。这里与管道不一样,管道是将一条命令的输出作为另外一条命令的 输入 。例如,我们可以执行以下命令来递归统计当前目录下,所有Go源文件的代码行总数:

    cat $(find -name "*.go") | wc -l
    

    或:

    cat `find -name "*.go"` | wc -l
    

    工具

    tmux

    tmux 是终端复用工具,简单地说,就是我们能用它在终端上创建多个 窗口,窗口之间可以通过快捷键快速切换。同时,每个窗口又可以任意分割成多个 窗格,光标可以通过快捷键在窗格之间快速跳转。
    tmux 的基本使用方法在网上有很多资料可以参考,这里就不赘述了。这里只叙述它的一些常规功能之外的优点,如下:

    • CS (Client-Server) 设计架构,我们可以与 Server 建立起多个会话,每个会话可以独立管理窗口。我们可以随时断开会话,然后关闭终端窗口,只要 Server 进程还在,我们就可以随时重建会话,会话中的窗口和其中运行的进程完全不会受影响。
    • 得益于 CS 架构,多个 Client 可以通过网络,与同一个 Server 的同一个会话建立连接, Server 的会话状态将实时推送到所有参与会话的 Client,也就是说,这是在做 直播,某一个 Client 的操作将对其他 Client 实时可见。
    • 还是得益于 CS 架构,再加上 tmux 对子命令的支持,我们可以通过 tmux 子命令与 Server 交互。这样,我们就可以把常用的 tmux 操作写成 shell 脚本,执行自动化操作。

    下面是一段 tmux 配置,可以加入到 ~/.tmux.conf 文件中,作用是将当前窗口分割成 字形的四个窗格,绑定的快捷键为 前缀键(默认Ctrl-B) Shift-W

    bind-key W split-window -h \; split-window \; select-pane -t 0 \;\
               split-window \; select-pane -t 0
    

    下面是一段 shell 脚本,作用是创建一个 tmux 会话,然后在该会话中创建编号为 0 - 9 的十个窗口,最后连接上该会话。脚本接受一个可选参数,如果该参数不为空,那么将作为会话的名字,否则,会话名字默认为 “0”。脚本执行时,需要确保当前没有连接 tmux 会话:

    #!/bin/bash
    
    if [ -z $1 ]; then
        SESSION_NAME="0"
    else
        SESSION_NAME=$1
    fi
    
    if $(tmux has-session -t "${SESSION_NAME}" > /dev/null 2>&1); then
        tmux attach-session -t "${SESSION_NAME}"
        exit 0
    fi
    
    tmux new-session -d -s "${SESSION_NAME}"
    
    for i in {1..9}
    do
        tmux new-window
    done
    
    tmux select-window -t "${SESSION_NAME}:0"
    tmux attach-session -t "${SESSION_NAME}"
    

    相关文章

      网友评论

        本文标题:Linux命令行效率提升技巧与工具

        本文链接:https://www.haomeiwen.com/subject/ioyhsctx.html