Shell 點檔案可以為你做點什麼

2019-10-03 12:35:00

了解如何使用組態檔來改善你的工作環境。

不要問你可以為你的 shell 點檔案dotfile做什麼,而是要問一個 shell 點檔案可以為你做什麼!

我一直在作業系統領域裡面打轉,但是在過去的幾年中,我的日常使用的一直是 Mac。很長一段時間,我都在使用 Bash,但是當幾個朋友開始把 zsh 當成宗教信仰時,我也試試了它。我沒用太長時間就喜歡上了它,幾年後,我越發喜歡它做的許多小事情。

我一直在使用 zsh(通過 Homebrew 提供,而不是由作業系統安裝的)和 Oh My Zsh 增強功能

本文中的範例是我的個人 .zshrc。大多數都可以直接用在 Bash 中,我覺得不是每個人都依賴於 Oh My Zsh,但是如果不用的話你的工作量可能會有所不同。曾經有一段時間,我同時為 zsh 和 Bash 維護一個 shell 點檔案,但是最終我還是放棄了我的 .bashrc

不偏執不行

如果你希望在各個作業系統上使用相同的點檔案,則需要讓你的點檔案聰明點。

### Mac 專用if [[ "$OSTYPE" == "darwin"* ]]; then        # Mac 專用內容在此

例如,我希望 Alt + 箭頭鍵 將游標按單詞移動而不是單個空格。為了在 iTerm2(我的首選終端)中實現這一目標,我將此程式碼段新增到了 .zshrc 的 Mac 專用部分:

### Mac 專用if [[ "$OSTYPE" == "darwin"* ]]; then        ### Mac 用於 iTerm2 的游標命令;對映 ctrl+arrows 或 alt+arrows 來快速移動        bindkey -e        bindkey '^[[1;9C' forward-word        bindkey '^[[1;9D' backward-word        bindkey '\e\e[D' backward-word        bindkey '\e\e[C' forward-wordfi

(LCTT 譯註:標題 “We’re all mad here” 是電影《愛麗絲夢遊仙境》中,微笑貓對愛麗絲講的一句話:“我們這兒全都是瘋的”。)

在家不工作

雖然我開始喜歡我的 Shell 點檔案了,但我並不總是想要家用計算機上的東西與工作的計算機上的東西一樣。解決此問題的一種方法是讓補充的點檔案在家中使用,而不是在工作中使用。以下是我的實現方式:

if [[ `egrep 'dnssuffix1|dnssuffix2' /etc/resolv.conf` ]]; then        if [ -e $HOME/.work ]                source $HOME/.work        else                echo "This looks like a work machine, but I can't find the ~/.work file"        fifi

在這種情況下,我根據我的工作 dns 字尾(或多個字尾,具體取決於你的情況)來提供(source)一個可以使我的工作環境更好的單獨檔案。

(LCTT 譯註:標題 “What about Bob?” 是 1991 年的美國電影《天才也瘋狂》。)

你該這麼做

現在可能是放棄使用波浪號(~)表示編寫指令碼時的主目錄的好時機。你會發現在某些上下文中無法識別它。養成使用環境變數 $HOME 的習慣,這將為你節省大量的故障排除時間和以後的工作。

如果你願意,合乎邏輯的擴充套件是應該包括特定於作業系統的點檔案。

(LCTT 譯註:標題 “That thing you do” 是 1996 年由湯姆·漢克斯執導的喜劇片《擋不住的奇蹟》。)

別指望記憶

我寫了那麼多 shell 指令碼,我真的再也不想寫指令碼了。並不是說 shell 指令碼不能滿足我大部分時間的需求,而是我發現寫 shell 指令碼,可能只是拼湊了一個膠帶式解決方案,而不是永久地解決問題。

同樣,我討厭記住事情,在我的整個職業生涯中,我經常不得不在一天之中就徹徹底底地改換環境。實際的結果是這些年來,我不得不一再重新學習很多東西。(“等等……這種語言使用哪種 for 迴圈結構?”)

因此,每隔一段時間我就會覺得自己厭倦了再次尋找做某事的方法。我改善生活的一種方法是新增別名。

對於任何一個使用作業系統的人來說,一個常見的情況是找出佔用了所有磁碟的內容。不幸的是,我從來沒有記住過這個咒語,所以我做了一個 shell 別名,創造性地叫做 bigdirs

alias bigdirs='du --max-depth=1 2> /dev/null | sort -n -r | head -n20'

雖然我可能不那麼懶惰,並實際記住了它,但是,那不太 Unix ……

(LCTT 譯註:標題 “Memory, all alone in the moonlight” 是一手英文老歌。)

輸錯的人們

使用 shell 別名改善我的生活的另一種方法是使我免於輸入錯誤。我不知道為什麼,但是我已經養成了這種討厭的習慣,在序列 ea 之後輸入 w,所以如果我想清除終端,我經常會輸入 cleawr。不幸的是,這對我的 shell 沒有任何意義。直到我新增了這個小東西:

alias cleawr='clear'

在 Windows 中有一個等效但更好的命令 cls,但我發現自己會在 Shell 也輸入它。看到你的 shell 表示抗議真令人沮喪,因此我新增:

alias cls='clear'

是的,我知道 ctrl + l,但是我從不使用它。

(LCTT 譯註:標題 “Typos, and the people who love them” 可能來自某部電影。)

要自娛自樂

工作壓力很大。有時你需要找點樂子。如果你的 shell 不知道它顯然應該執行的命令,則可能你想直接讓它聳聳肩!你可以使用以下功能執行此操作:

shrug() { echo "¯\_(ツ)_/¯"; }

如果還不行,也許你需要掀桌不幹了:

fliptable() { echo "(╯°□°)╯ ┻━┻"; } # 掀桌,用法範例: fsck -y /dev/sdb1 || fliptable

想想看,當我想掀桌子時而我不記得我給它起了個什麼名字,我會有多沮喪和失望,所以我新增了更多的 shell 別名:

alias flipdesk='fliptable'alias deskflip='fliptable'alias tableflip='fliptable'

而有時你需要慶祝一下:

disco() {        echo "(•_•)"        echo "<)   )╯"        echo " /    \ "        echo ""        echo "\(•_•)"        echo " (   (>"        echo " /    \ "        echo ""        echo " (•_•)"        echo "<)   )>"        echo " /    \ "}

通常,我會將這些命令的輸出通過管道傳遞到 pbcopy,並將其貼上到我正在使用的相關聊天工具中。

我從一個我關注的一個叫 “Command Line Magic” @ climagic 的 Twitter 帳戶得到了下面這個有趣的函數。自從我現在住在佛羅里達州以來,我很高興看到我這一生中唯一的一次下雪:

snow() {        clear;while :;do echo $LINES $COLUMNS $(($RANDOM%$COLUMNS));sleep 0.1;done|gawk '{a[$3]=0;for(x in a) {o=a[x];a[x]=a[x]+1;printf "\033[%s;%sH ",o,x;printf "\033[%s;%sH*\033[0;0H",a[x],x;}}'}

(LCTT 譯註:標題 “Amuse yourself” 是 1936 年的美國電影《自娛自樂》)

函數的樂趣

我們已經看到了一些我使用的函數範例。由於這些範例中幾乎不需要引數,因此可以將它們作為別名來完成。 當比一個短句更長時,我出於個人喜好使用函數。

在我職業生涯的很多時期我都執行過 Graphite,這是一個開源、可延伸的時間序列指標解決方案。 在很多的情況下,我需要將度量路徑(用句點表示)轉換到檔案系統路徑(用斜槓表示),反之亦然,擁有專用於這些任務的函數就變得很有用:

# 在 Graphite 指標和檔案路徑之間轉換很有用function dottoslash() {        echo $1 | sed 's/\./\//g'}function slashtodot() {        echo $1 | sed 's/\//\./g'}

在我的另外一段職業生涯裡,我執行了很多 Kubernetes。如果你對執行 Kubernetes 不熟悉,你需要編寫很多 YAML。不幸的是,一不小心就會編寫了無效的 YAML。更糟糕的是,Kubernetes 不會在嘗試應用 YAML 之前對其進行驗證,因此,除非你應用它,否則你不會發現它是無效的。除非你先進行驗證:

function yamllint() {        for i in $(find . -name '*.yml' -o -name '*.yaml'); do echo $i; ruby -e "require 'yaml';YAML.load_file(\"$i\")"; done}

因為我厭倦了偶爾破壞客戶的設定而讓自己感到尷尬,所以我寫了這個小片段並將其作為提交前掛鉤新增到我所有相關的儲存庫中。在持續整合過程中,類似的內容將非常有幫助,尤其是在你作為團隊成員的情況下。

(LCTT 譯註:哦抱歉,我不知道這個標題的出處。)

手指不聽話

我曾經是一位出色的盲打打字員。但那些日子已經一去不回。我的打字錯誤超出了我的想象。

在各種時期,我多次用過 Chef 或 Kubernetes。對我來說幸運的是,我從未同時使用過這兩者。

Chef 生態系統的一部分是 Test Kitchen,它是加快測試的一組工具,可通過命令 kitchen test 來呼叫。Kubernetes 使用 CLI 工具 kubectl 進行管理。這兩個命令都需要幾個子命令,並且這兩者都不會特別順暢地移動手指。

我沒有建立一堆“輸錯別名”,而是將這兩個命令別名為 k

alias k='kitchen test $@'

alias k='kubectl $@'

(LCTT 譯註:標題 “Oh, fingers, where art thou?” 演繹自《O Brother, Where Art Thou?》,這是 2000 年美國的一部電影《逃獄三王》。)

分裂與合併

我職業生涯的後半截涉及與其他人一起編寫更多程式碼。我曾在許多環境中工作過,在這些環境中,我們在帳戶中復刻了儲存庫副本,並將拉取請求用作稽核過程的一部分。當我想確保給定儲存庫的復刻與父版本保持最新時,我使用 fetchupstream

alias fetchupstream='git fetch upstream && git checkout master && git merge upstream/master && git push'

(LCTT 譯註:標題 “Timesplitters” 是一款電動遊戲《時空分裂者》。)

顏色之榮耀

我喜歡顏色。它可以使 diff 之類的東西更易於使用。

alias diff='colordiff'

我覺得彩色的手冊頁是個巧妙的技巧,因此我合併了以下函數:

# 彩色化手冊頁,來自:# http://boredzo.org/blog/archives/2016-08-15/colorized-man-pages-understood-and-customizedman() {        env \                LESS_TERMCAP_md=$(printf "\e[1;36m") \                LESS_TERMCAP_me=$(printf "\e[0m") \                LESS_TERMCAP_se=$(printf "\e[0m") \                LESS_TERMCAP_so=$(printf "\e[1;44;33m") \                LESS_TERMCAP_ue=$(printf "\e[0m") \                LESS_TERMCAP_us=$(printf "\e[1;32m") \                man "$@"}

我喜歡命令 which,但它只是告訴你正在執行的命令在檔案系統中的位置,除非它是 Shell 函數才能告訴你更多。在多個級聯的點檔案之後,有時會不清楚函數的定義位置或作用。事實證明,whencetype 命令可以幫助解決這一問題。

# 函數定義在哪裡?whichfunc() {        whence -v $1        type -a $1}

(LCTT 譯註:標題“Mine eyes have seen the glory of the coming of color” 演繹自歌曲 《Mine Eyes Have Seen The Glory Of The Coming Of The Lord》)

總結

希望本文對你有所幫助,並能激發你找到改善日常使用 Shell 的方法。這些方法不必龐大、新穎或複雜。它們可能會解決一些微小但頻繁的摩擦、建立捷徑,甚至提供減少常見輸入錯誤的解決方案。

歡迎你瀏覽我的 dotfiles 儲存庫,但我要警示你,這樣做可能會花費很多時間。請隨意使用你認為有幫助的任何東西,並互相取長補短。