[英]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.