4

我在 Ubuntu 12.04 上的 VM 中运行多个 Web 应用程序。

当我 ssh 进入我的虚拟机时,我发现自己经常输入以下内容。

  • 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

我哪里做错了?

编辑2:

当我尝试在 .bashrc 中添加命令时,我已在 command not found 消息处将错误改写为另一个问题。

4

6 回答 6

3

为每个定义一个别名肯定会起作用。但是由于您有多个遵循模式的所需快捷方式,因此请考虑使用函数。

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

用法:

go_app 1

将函数定义放在 ~/.bashrc 中。

于 2013-11-01T03:04:44.850 回答
2

您可以通过将以下内容放在 .bash_profile 中来使用别名。

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

之后,键入 go_app1 应该会更改您的目录。

于 2013-11-01T03:02:07.070 回答
2

通过 bash 命令历史搜索是否是一个足够好的解决方案?我也经常要登录到很长的目录结构,但我通常是 Ctrl-R 通过。例如,如果我最近 cd-ed 进入了你的 app1.com,我会按 Ctrl-R 然后键入 app1.com,最后一个使用 app1.com 的命令会出现,此时你按下回车键就完成了. 如果“cd”不是那个,你再按几次 Ctrl-R 直到它出现。

更多细节: http: //www.catonmat.net/blog/the-definitive-guide-to-bash-command-line-history/

当然,这仅在您关心键入多少时才有效,而不是在您尝试以编程方式执行此操作时,并且仅当“cd”命令在具有“app1.com”的命令列表中相当新时才有效" (或任何其他简短的区分模式)明确。

于 2013-11-01T03:59:36.953 回答
0

我会将$CDPATH变量 (in bash) 设置为要搜索的所有目录,包括当前目录(首先),例如:

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

那我只能说:

 cd app1.com

鉴于此,目录名称很短,我可以输入(而不是通过历史搜索它们)

于 2013-11-01T06:25:49.770 回答
0

将此添加到您的.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')
}

这将创建go_appX具有X编号的函数,使得该目录/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,确保它是绝对路径。
  • 选项卡完成课程效果很好(选项卡选项卡将向您展示可能性)。
  • 如果您删除一些目录,您可能希望 a_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=''and来向你展示在解析.-d ''-printf '%f\0'findfind


我仍然担心函数中的findin _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

抱歉,这篇冗长的帖子很混乱……我打字时或多或少在思考(不好做!),我从不想删除前面的部分,因为它们包含有趣的东西。


编辑. 现在,为了让这篇文章更长,这里是一样的,但是这将为里面go_X的每个目录创建一个函数,这样只包含字符:。把它放在你的:X.com/var/virtualX[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
于 2013-11-01T11:28:56.653 回答
0

改进 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,没有参数会将您踢回您的家(因为最后一个命令cd没有进一步的参数)。

于 2013-11-01T10:46:48.223 回答