不可或缺的 Bash 別名

2019-08-03 09:59:00

厭倦了一遍又一遍地輸入相同的長命令?你覺得在命令列上工作效率低嗎?Bash 別名可以為你創造一個與眾不同的世界。

Bash 別名是一種用新的命令補充或覆蓋 Bash 命令的方法。Bash 別名使使用者可以輕鬆地在 POSIX 終端中自定義其體驗。它們通常定義在 $HOME/.bashrc$HOME/bash_aliases 中(它是由 $HOME/.bashrc 載入的)。

大多數發行版在新使用者帳戶的預設 .bashrc 檔案中至少新增了一些流行的別名。這些可以用來簡單演示 Bash 別名的語法:

alias ls='ls -F'alias ll='ls -lh'

但並非所有發行版都附帶預先新增好的別名。如果你想手動新增別名,則必須將它們載入到當前的 Bash 對談中:

$ source ~/.bashrc

否則,你可以關閉終端並重新開啟它,以便重新載入其組態檔。

通過 Bash 初始化指令碼中定義的那些別名,你可以鍵入 ll 而得到 ls -l 的結果,當你鍵入 ls 時,得到也不是原來的 ls 的普通輸出。

那些別名很棒,但它們只是淺嚐輒止。以下是十大 Bash 別名,一旦你試過它們,你會發現再也不能離開它們。

首先設定

在開始之前,建立一個名為 ~/.bash_aliases 的檔案:

$ touch ~/.bash_aliases

然後,確認這些程式碼出現在你的 ~/.bashrc 檔案當中:

if [ -e $HOME/.bash_aliases ]; then    source $HOME/.bash_aliasesfi

如果你想親自嘗試本文中的任何別名,請將它們輸入到 .bash_aliases 檔案當中,然後使用 source ~/.bashrc 命令將它們載入到當前 Bash 對談中。

按檔案大小排序

如果你一開始使用過 GNOME 中的 Nautilus、MacOS 中的 Finder 或 Windows 中的資源管理器等 GUI 檔案管理器,那麼你很可能習慣了按檔案大小排序檔案列表。你也可以在終端上做到這一點,但這條命令不是很簡潔。

將此別名新增到 GNU 系統上的設定中:

alias lt='ls --human-readable --size -1 -S --classify'

此別名將 lt 替換為 ls 命令,該命令在單個列中顯示每個專案的大小,然後按大小對其進行排序,並使用符號表示檔案型別。載入新別名,然後試一下:

$ source ~/.bashrc$ lttotal 344K140K configure* 44K aclocal.m4 36K LICENSE 32K config.status* 24K Makefile 24K Makefile.in 12K config.log8.0K README.md4.0K info.slackermedia.Git-portal.json4.0K git-portal.spec4.0K flatpak.path.patch4.0K Makefile.am*4.0K dot-gitlab.ci.yml4.0K configure.ac*   0 autom4te.cache/   0 share/   0 bin/   0 install-sh@   0 compile@   0 missing@   0 COPYING@

在 MacOS 或 BSD 上,ls 命令沒有相同的選項,因此這個別名可以改為:

alias lt='du -sh * | sort -h'

這個版本的結果稍有不同:

$ du -sh * | sort -h0       compile0       COPYING0       install-sh0       missing4.0K    configure.ac4.0K    dot-gitlab.ci.yml4.0K    flatpak.path.patch4.0K    git-portal.spec4.0K    info.slackermedia.Git-portal.json4.0K    Makefile.am8.0K    README.md12K     config.log16K     bin24K     Makefile24K     Makefile.in32K     config.status36K     LICENSE44K     aclocal.m460K     share140K    configure476K    autom4te.cache

實際上,即使在 Linux上,上面這個命令也很有用,因為使用 ls 列出的目錄和符號連結的大小為 0,這可能不是你真正想要的資訊。使用哪個看你自己的喜好。

感謝 Brad Alexander 提供的這個別名的思路。

只檢視掛載的驅動器

mount 命令過去很簡單。只需一個命令,你就可以獲得計算機上所有已掛載的檔案系統的列表,它經常用於概覽連線到工作站有哪些驅動器。在過去看到超過三、四個條目就會令人印象深刻,因為大多數計算機沒有那麼多的 USB 埠,因此這個結果還是比較好檢視的。

現在計算機有點複雜,有 LVM、物理驅動器、網路儲存和虛擬檔案系統,mount 的結果就很難一目了然:

sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime,seclabel)proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)devtmpfs on /dev type devtmpfs (rw,nosuid,seclabel,size=8131024k,nr_inodes=2032756,mode=755)securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)[...]/dev/nvme0n1p2 on /boot type ext4 (rw,relatime,seclabel)/dev/nvme0n1p1 on /boot/efi type vfat (rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=ascii,shortname=winnt,errors=remount-ro)[...]gvfsd-fuse on /run/user/100977/gvfs type fuse.gvfsd-fuse (rw,nosuid,nodev,relatime,user_id=100977,group_id=100977)/dev/sda1 on /run/media/seth/pocket type ext4 (rw,nosuid,nodev,relatime,seclabel,uhelper=udisks2)/dev/sdc1 on /run/media/seth/trip type ext4 (rw,nosuid,nodev,relatime,seclabel,uhelper=udisks2)binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)

要解決這個問題,試試這個別名:

alias mnt='mount | awk -F' ' '{ printf "%s\t%s\n",$1,$3; }' | column -t | egrep ^/dev/ | sort'

此別名使用 awk 按列解析 mount 的輸出,將輸出減少到你可能想要查詢的內容(掛載了哪些硬碟機,而不是檔案系統):

$ mnt/dev/mapper/fedora-root  //dev/nvme0n1p1           /boot/efi/dev/nvme0n1p2           /boot/dev/sda1                /run/media/seth/pocket/dev/sdc1                /run/media/seth/trip

在 MacOS 上,mount 命令不提供非常詳細的輸出,因此這個別名可能過度精簡了。但是,如果你更喜歡簡潔的報告,請嘗試以下方法:

alias mnt='mount | grep -E ^/dev | column -t'

結果:

$ mnt/dev/disk1s1  on  /                (apfs,  local,  journaled)/dev/disk1s4  on  /private/var/vm  (apfs,  local,  noexec,     journaled,  noatime,  nobrowse)

在你的 grep 歷史中查詢命令

有時你好不容易弄清楚了如何在終端完成某件事,並覺得自己永遠不會忘記你剛學到的東西。然後,一個小時過去之後你就完全忘記了你做了什麼。

搜尋 Bash 歷史記錄是每個人不時要做的事情。如果你確切地知道要搜尋的內容,可以使用 Ctrl + R 對歷史記錄進行反向搜尋,但有時你無法記住要查詢的確切命令。

這是使該任務更容易的別名:

alias gh='history|grep'

這是如何使用的例子:

$ gh bash482 cat ~/.bashrc | grep _alias498 emacs ~/.bashrc530 emacs ~/.bash_aliases531 source ~/.bashrc

按修改時間排序

每個星期一都會這樣:你坐在你的電腦前開始工作,你開啟一個終端,你發現你已經忘記了上週五你在做什麼。你需要的是列出最近修改的檔案的別名。

你可以使用 ls 命令建立別名,以幫助你找到上次離開的位置:

alias left='ls -t -1'

輸出很簡單,但如果你願意,可以使用 --long 選項擴充套件它。這個別名列出的顯示如下:

$ leftdemo.jpegdemo.xcfdesign-proposal.mdrejects.txtbrainstorm.txtquery-letter.xml

檔案計數

如果你需要知道目錄中有多少檔案,那麼該解決方案是 UNIX 命令構造的最典型範例之一:使用 ls 命令列出檔案,用-1 選項將其輸出控制為只有一列,然後輸出到 wc(單詞計數)命令的管道,以計算有多少行。

這是 UNIX 理念如何允許使用者使用小型的系統元件構建自己的解決方案的精彩演示。如果你碰巧每天都要做幾次,這個命令組合也要輸入很多字母,如果沒有使用 -R 選項,它就不能用於目錄,這會為輸出引入新行並導致無用的結果。

而這個別名使這個過程變得簡單:

alias count='find . -type f | wc -l'

這個別名會計算檔案,忽略目錄,但不會忽略目錄的內容。如果你有一個包含兩個目錄的專案資料夾,每個目錄包含兩個檔案,則該別名將返回 4,因為整個專案中有 4 個檔案。

$ lsfoo   bar$ count4

建立 Python 虛擬環境

你用 Python 程式設計嗎?

你用 Python 編寫了很多程式嗎?

如果是這樣,那麼你就知道建立 Python 虛擬環境至少需要 53 次擊鍵。

這個數位裡有 49 次是多餘的,它很容易被兩個名為 veva 的新別名所解決:

alias ve='python3 -m venv ./venv'alias va='source ./venv/bin/activate'

執行 ve 會建立一個名為 venv 的新目錄,其中包含 Python 3 的常用虛擬環境檔案系統。va 別名在當前 shell 中的啟用該環境:

$ cd my-project$ ve$ va(venv) $

增加一個複製進度條

每個人都會吐槽進度條,因為它們似乎總是不合時宜。然而,在內心深處,我們似乎都想要它們。UNIX 的 cp 命令沒有進度條,但它有一個 -v 選項用於顯示詳細資訊,它回顯了複製的每個檔名到終端。這是一個相當不錯的技巧,但是當你複製一個大檔案並且想要了解還有多少檔案尚未傳輸時,它的作用就沒那麼大了。

pv 命令可以在複製期間提供進度條,但它並不常用。另一方面,rsync 命令包含在幾乎所有的 POSIX 系統的預設安裝中,並且它被普遍認為是遠端和本地複製檔案的最智慧方法之一。

更好的是,它有一個內建的進度條。

alias cpv='rsync -ah --info=progress2'

像使用 cp 命令一樣使用此別名:

$ cpv bigfile.flac /run/media/seth/audio/          3.83M 6%  213.15MB/s    0:00:00 (xfr#4, to-chk=0/4)

使用此命令的一個有趣的副作用是 rsync 無需 -r 標誌就可以複製檔案和目錄,而 cp 則需要。

避免意外刪除

你不應該使用 rm 命令。rm 手冊甚至這樣說:

警告:如果使用 rm 刪除檔案,通常可以恢復該檔案的內容。如果你想要更加確保內容真正無法恢復,請考慮使用 shred

如果要刪除檔案,則應將檔案移動到“廢紙簍”,就像使用桌面時一樣。

POSIX 使這很簡單,因為垃圾桶是檔案系統中可存取的一個實際位置。該位置可能會發生變化,具體取決於你的平台:在 FreeDesktop 上,“垃圾桶”位於 ~/.local/share/Trash,而在 MacOS 上則是 ~/.Trash,但無論如何,它只是一個目錄,你可以將檔案藏在那個看不見的地方,直到你準備永久刪除它們為止。

這個簡單的別名提供了一種從終端將檔案扔進垃圾桶的方法:

alias tcn='mv --force -t ~/.local/share/Trash '

該別名使用一個鮮為人知的 mv 標誌(-t),使你能夠提供作為最終移動目標的引數,而忽略了首先列出要移動的檔案的通常要求。現在,你可以使用新命令將檔案和資料夾移動到系統垃圾桶:

$ lsfoo  bar$ tcn foo$ lsbar

現在檔案已“消失”,只有在你一頭冷汗的時候才意識到你還需要它。此時,你可以從系統垃圾桶中搶救該檔案;這肯定可以給 Bash 和 mv 開發人員提供一些幫助。

注意:如果你需要一個具有更好的 FreeDesktop 相容性的更強大的垃圾桶命令,請參閱 Trashy

簡化 Git 工作流

每個人都有自己獨特的工作流程,但無論如何,通常都會有重複的任務。如果你經常使用 Git,那麼你可能會發現自己經常重複的一些操作序列。也許你會發現自己回到主分支並整天一遍又一遍地拉取最新的變化,或者你可能發現自己建立了標籤然後將它們推到遠端,抑或可能完全是其它的什麼東西。

無論讓你厭倦一遍遍輸入的 Git 魔咒是甚麼,你都可以通過 Bash 別名減輕一些痛苦。很大程度上,由於它能夠將引數傳遞給勾點,Git 擁有著豐富的內省命令,可以讓你不必在 Bash 中執行那些醜陋冗長的命令。

例如,雖然你可能很難在 Bash 中找到專案的頂級目錄(就 Bash 而言,它是一個完全隨意的名稱,因為計算機的絕對頂級是根目錄),但 Git 可以通過簡單的查詢找到專案的頂級目錄。如果你研究過 Git 勾點,你會發現自己能夠找到 Bash 一無所知的各種資訊,而你可以利用 Bash 別名來利用這些資訊。

這是一個來查詢 Git 專案的頂級目錄的別名,無論你當前在哪個專案中工作,都可以將目錄改變為頂級目錄,切換到主分支,並執行 Git 拉取:

alias startgit='cd `git rev-parse --show-toplevel` && git checkout master && git pull'

這種別名絕不是一個普遍有用的別名,但它演示了一個相對簡單的別名如何能夠消除大量繁瑣的導航、命令和等待提示。

一個更簡單,可能更通用的別名將使你返回到 Git 專案的頂級目錄。這個別名非常有用,因為當你在一個專案上工作時,該專案或多或少會成為你的“臨時家目錄”。它應該像回家一樣簡單,就像回你真正的家一樣,這裡有一個別名:

alias cg='cd `git rev-parse --show-toplevel`'

現在,命令 cg 將你帶到 Git 專案的頂部,無論你下潛的目錄結構有多深。

切換目錄並同時檢視目錄內容

(據稱)曾經一位著名科學家提出過,我們可以通過收集極客輸入 cd 後跟 ls 消耗的能量來解決地球上的許多能量問題。

這是一種常見的用法,因為通常當你更改目錄時,你都會有檢視周圍的內容的衝動或需要。

但是在你的計算機的目錄樹中移動並不一定是一個走走停停的過程。

這是一個作弊,因為它根本不是別名,但它是探索 Bash 功能的一個很好的藉口。雖然別名非常適合快速替換一個命令,但 Bash 也允許你在 .bashrc 檔案中新增本地函數(或者你載入到 .bashrc 中的單獨函數檔案,就像你的別名檔案一樣)。

為了保持模組化,建立一個名為 ~/.bash_functions 的新檔案,然後讓你的 .bashrc 載入它:

if [ -e $HOME/.bash_functions ]; then    source $HOME/.bash_functionsfi

在該函數檔案中,新增這些程式碼:

function cl() {    DIR="$*";    # if no DIR given, go home    if [ $# -lt 1 ]; then         DIR=$HOME;    fi;    builtin cd "${DIR}" && \    # use your preferred ls command    ls -F --color=auto}

將函數載入到 Bash 對談中,然後嘗試:

$ source ~/.bash_functions$ cl Documentsfoo bar baz$ pwd/home/seth/Documents$ cl ..Desktop  Documents  Downloads[...]$ pwd/home/seth

函數比別名更靈活,但有了這種靈活性,你就有責任確保程式碼有意義並達到你的期望。別名是簡單的,所以要保持簡單而有用。要正式修改 Bash 的行為,請使用儲存到 PATH 環境變數中某個位置的函數或自定義的 shell 指令碼。

附註,有一些巧妙的奇技淫巧來實現 cdls 序列作為別名,所以如果你足夠耐心,那麼即使是一個簡單的別名也永無止限。

開始別名化和函數化吧

可以客製化你的環境使得 Linux 變得如此有趣,提高效率使得 Linux 可以改變生活。開始使用簡單的別名,進而使用函數,並在評論中發布你必須擁有的別名!