如何在bashshell中编写漂亮优雅的linux命令
我在Ubuntu 12.04上的虚拟机上运行了几个web应用程序 我发现自己在ssh到VM中时经常输入以下内容如何在bashshell中编写漂亮优雅的linux命令,linux,bash,shell,Linux,Bash,Shell,我在Ubuntu 12.04上的虚拟机上运行了几个web应用程序 我发现自己在ssh到VM中时经常输入以下内容 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 -a
cd/var/virtual/app1.com/
cd/var/virtual/app2.com/
cd/var/virtual/app3.com/
go_app1
go_app2
go_app3
./GoApp.sh -app app1
我想通过简单地键入go_app1使其更加优雅
建议
编辑:
我使用了最高评级的答案,我在Ubuntu中得到了这个错误消息
我哪里出错了
EDIT2:
我已在此处将错误改写为另一个问题。您可以通过在.bash\u配置文件中放置以下内容来使用别名
alias go_app1='cd /var/virtual/app1.com/'
这样做之后,键入go_app1应该会更改您的目录。为每个目录定义一个别名肯定会起作用。但是,由于您有多个期望的快捷方式跟随一个模式,请考虑一个函数。
function go_app() { cd /var/virtual/app$1.com/; }
用法:
go_app 1
将函数定义放在~/.bashrc中。搜索bash命令历史记录是否足够好?我还经常需要登录到长目录结构,但我通常通过Ctrl-R进行登录。例如,如果我最近在你的app1.com上安装了cd,我会按 Ctrl-R 然后键入app1.com,将显示使用app1.com的最后一个命令,此时按enter键即可完成。如果不是“cd”,请再按Ctrl-R几次,直到它出现 更详细一点:
当然,只有当您关心键入的数量,而不是试图以编程方式执行此操作时,并且只有当“cd”命令在显式包含“app1.com”(或任何其他简短区分模式)的命令列表中是相当新的命令时,这才有效。我将设置
$CDPATH
变量(在bash
)要搜索的所有目录,包括当前目录(首先),如:
鉴于此,目录名很短,我可以键入(而不是在历史记录中搜索)改进corkin别名建议,但鉴于“命名”的灵活性(参数为app1.com、app2.com等),此解决方案使用单个别名解决此问题:
alias go_app='cd /var/virtual/; cd '
后来,
go_app app1.com
将cd
放入/var/virtual/app1.com/。关于命名:我将它命名为cd\u app
。
另一方面,没有参数的go_应用程序将把你踢回你的家(因为最后一个命令是没有参数的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')
}
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)
}
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
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
完成了
如果创建了新目录,则只需重新启动功能\u make\u go\u apps
这种方法满足OP的所有要求,并且足够通用,能够处理任意数量的目录
eval
是一种邪恶的方法,但使用起来是安全的(使用经过净化的变量读取,尽管在这里它是无用的;但是如果有一天你想推广这个方法,你至少会纠正这一部分)
除非您完全知道自己在做什么:注意包含空格、换行符、尾随换行符等的文件名,否则不要尝试推广此方法。
备注。
- 如果要更改位置
,只需更改局部变量/var/virtual
,确保它是绝对路径r
- Tab完成课程效果非常好(Tab Tab将向您展示各种可能性)
- 如果删除某些目录,您可能希望
只保留相关的\u clean\u go\u apps
。一种可能性是(它将进入您的go\u appX
): 我标记了变量.bashrc
\u go\u apps\u basedir
,这样就不会无意中更改它。这次我选择在read中使用readonly
和IFS='
,在-d'
命令中使用find
,向您展示如何在解析-printf'%f\0'
的输出时执行安全操作find
我仍然担心
函数中的\u make\u go\u apps
,因为它不是100%纯bash解决方案。下面是一个100%纯bash解决方案:find
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
您可以直接使用
,跳过选项名称……我的建议是:如果您想要优雅,请为bash脚本选择更优雅的名称,并将它们放在$PATH中的目录中。这样做,你就可以输入/GoApp.sh app1
,这在我的书中肯定算是优雅的。排名靠前的答案并不总是最好的。请考虑我的回答,它满足你的100%的要求!我喜欢这种方法,但是如果只让函数go-app1
然后按照您的指示使用它,会不会更容易一些。。。(我想OP是说,go_app(){cd/var/virtual/app${1}.com/}
是一个shell脚本,负责GoApp
ing…)是的。看来GoApp.sh只是解决实际问题的一种可能的方法。谢谢。你好,我在用ubuntu。我一直收到这个错误消息。对于linux用户,它是~/.bashrc文件。然后,如果你有1000个应用程序目录,这不是一个好的解决方案。在这种情况下,我更喜欢这个:;)@Idrissneumann我尝试了你的建议,但不断收到此命令未找到消息。我理解你为什么不想删除你前面的部分,但是你能为你建议的答案写一个简明的摘要吗?现在,我不能确定我应该采纳你答案的哪一部分。@KimSia最下面的部分很好:把它放在cd
的底部,当你打开一个新的终端时.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
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
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