簡體   English   中英

如何在bash shell中編寫一個優雅的linux命令

[英]how to write a beautifully elegant linux command in bash shell

我正在我的VM中運行多個Web應用程序,這些應用程序位於Ubuntu 12.04上。

當我進入我的虛擬機時,我發現自己經常輸入以下內容。

  • cd /var/virtual/app1.com/
  • cd /var/virtual/app2.com/
  • cd /var/virtual/app3.com/

每行代表一個單獨的webapp根目錄,供我執行某些指令。

這是懶惰的程序員,詢問我是否有辦法輸入。

  • go_app1
  • go_app2
  • go_app3

我知道如何使用bash腳本執行上述操作。

但我最終會打字

./GoApp.sh -app app1

我想通過輸入go_app1來使它更優雅。

建議嗎?

編輯:

我使用了頂級答案,我在Ubuntu中收到此錯誤消息。

https://gist.github.com/simkimsia/7336019

我哪里做錯了?

EDIT2:

當我嘗試在.bashrc中添加命令時,我已經命令未找到消息時將錯誤重寫為另一個問題。

為每個定義別名肯定會有效。 但由於您在模式后面有多個所需的快捷方式,因此請考慮一個函數。

function go_app() { cd /var/virtual/app$1.com/; }

用法:

go_app 1

將函數定義放在〜/ .bashrc中。

您可以通過將以下內容放在.bash_profile中來使用別名。

alias go_app1='cd /var/virtual/app1.com/'

完成后,鍵入go_app1應該更改您的目錄。

通過bash命令歷史搜索是否是一個足夠好的解決方案? 我還經常需要登錄長目錄結構,但我通常都是Ctrl-R。 例如,如果我最近剛進入你的app1.com,我會按Ctrl-R然后輸入app1.com,然后會出現使用app1.com的最后一個命令,此時你按Enter鍵就完成了。 如果“cd”不是那個,則再按Ctrl-R幾次直到它出現。

更詳細一點: http//www.catonmat.net/blog/the-definitive-guide-to-bash-command-line-history/

當然,這只有在你關心鍵入多少時才有效,而不是你想以編程方式執行此操作,並且只有“cd”命令在具有“app1.com”的命令列表中相當近。 “(或任何其他短的區別模式)明確。

我將$CDPATH變量(在bash )設置為要搜索的所有目錄,包括當前目錄(首先),如:

 export CDPATH=.:/var/virtual:<other-dirs>

然后我可以說:

 cd app1.com

鑒於此,目錄名稱很短,我可以輸入(而不是通過歷史記錄搜索它們)

改進corkin別名建議,但考慮到“命名”的靈活性(使用參數app1.com,app2.com,...),此解決方案使用單個別名解決它:

alias go_app='cd /var/virtual/; cd '

然后,

go_app app1.com

cd到/var/virtual/app1.com/。 在命名時:我會將其命名為cd_app go_app沒有參數的go_app會將你帶回家(因為最后一個命令是沒有進一步參數的cd )。

在你的.bashrc添加:

_make_go_apps() {
    local r=/var/virtual
    local d qd
    while read d; do
        printf -v qd '%q' "$r/$d"
        eval "go_${d%.com}() { cd -- $qd; }"
    done < <( find "$r" -maxdepth 1 -regex ".*/app[0-9]+\.com" -type d -printf '%f\n')
}

這將創建帶有X的函數go_appX ,使得目錄/var/virtual/appX.com存在,並且該函數在被調用時將只是cd進入該目錄。

看(別擔心,我在沙盒中):

# mkdir -p /var/virtual/app{1..50}.com
# _make_go_apps
# go_app42
# pwd
/var/virtual/app42

完成!

如果創建了新目錄,則只需重新啟動函數_make_go_apps

這種方法滿足了所有OP的要求,並且通用性足以應對任意數量的目錄。

eval是邪惡的,但是以安全的方式使用(使用已消毒的變量讀取,即使它在這里沒用;但如果有一天你想要推廣這種方法,你至少會使這部分正確)。

除非你完全知道自己在做什么,否則不要試圖概括這個方法:處理包含空格,換行符,尾隨換行符等的文件名。

備注。

  • 如果要更改位置/var/virtual ,只需更改局部變量r ,確保它是絕對路徑。
  • 選項卡完成當然非常有效(選項卡選項卡將顯示可能性)。
  • 如果刪除某些目錄,您可能希望_clean_go_apps僅保留相關的go_appX 一種可能性是(它將進入你的.bashrc ):

     clean_go_apps() { local r=/var/virtual local f while read _ _ f; do [[ $f =~ ^go_app[[:digit:]]+$ ]] || continue [[ -d $r/${f#go_}.com ]] && continue unset -f $f done < <(declare -F) } 

    在這種情況下,請閱讀下一部分。


然后你會發現在兩個不同的地方使用/var/virtual並不是一個好主意,所以你需要使用一個全局變量,你最終會在你的.bashrc

readonly _go_apps_basedir=/var/virtual
make_go_apps() {
    local d qd
    while IFS= read -d '' d; do
        printf -v qd '%q' "$_go_apps_basedir/$d"
        eval "go_${d%.com}() { cd -- $qd; }"
    done < <( find "$_go_apps_basedir" -maxdepth 1 -regex ".*/app[0-9]+\.com" -type d -printf '%f\0')
}

clean_go_apps() {
    local f
    while read _ _ f; do
        [[ $f =~ ^go_app[[:digit:]]+$ ]] || continue
        [[ -d "$_go_apps_basedir/${f#go_}.com" ]] && continue
        unset -f $f
    done < <(declare -F)
}

make_go_apps

我將變量_go_apps_basedir標記為readonly ,因此不會無意中更改。 這次我選擇在read中使用IFS=''-d '' ,以及在find命令中使用-printf '%f\\0' ,以向您展示在解析find輸出時如何安全操作。


我仍然關心find_make_go_apps功能,因為它不是一個100%的純bash的解決方案。 這是一個100%純粹的bash解決方案:

readonly _go_apps_basedir=/var/virtual
make_go_apps() {
    local f d qd saved_shopt
    saved_shopt=$(shopt -p)
    shopt -s extglob nullglob
    for d in "$_go_apps_basedir"/app+([[:digit:]]).com/; do
        f=${d#$_go_apps_basedir/}
        printf -v qd '%q' "$d"
        eval "go_${f%.com/}() { cd -- $qd; }"
    done
    eval "$saved_shopt"
}

clean_go_apps() {
    local f
    while read _ _ f; do
        [[ $f =~ ^go_app[[:digit:]]+$ ]] || continue
        [[ -d "$_go_apps_basedir/${f#go_}.com" ]] && continue
        unset -f $f
    done < <(declare -F)
}

make_go_apps

對不起 ,這個長篇大論的帖子......我或多或少地在打字時思考(不好做!),我從來沒有想要刪除之前的部分,因為它們包含有趣的東西。


編輯 現在,為了使這篇文章更長,這里是相同的,但是這將為/var/virtual每個目錄X.com創建一個go_X函數,這樣X只包含字符: [0-9a-zA-Z\\-\\._] 把它放在你的.bashrc

readonly _go_apps_basedir=/var/virtual
make_go_functions() {
    local f d qd saved_shopt
    saved_shopt=$(shopt -p)
    shopt -s extglob nullglob
    for d in "$_go_apps_basedir"/+([[:alpha:][:digit:]\-\._]).com/; do
        f=${d#$_go_apps_basedir/}
        printf -v qd '%q' "$d"
        eval "go_${f%.com/}() { cd -- $qd; }"
    done
    eval "$saved_shopt"
}

clean_go_apps() {
    local f
    while read _ _ f; do
        [[ $f =~ ^go_.+$ ]] || continue
        [[ -d "$_go_apps_basedir/${f#go_}.com" ]] && continue
        unset -f $f
    done < <(declare -F)
}

make_go_functions

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM