【问题标题】:Bash: cd to directory provided by program outputBash: cd 到程序输出提供的目录
【发布时间】:2013-10-28 18:13:18
【问题描述】:

我有一个返回系统路径的简短 shell 程序。我想要做的是使用 bash 别名 CD 到该路径。

我的理想输出是

~$ pwd
    /home/username
~$ mark home
~$ cd /
/$ pwd
    /
/$ place home
~$ pwd
    /home/username

我有“标记”部分工作,但“地方”没有:

alias place="cd \"~/marker.sh go $@\";"

我的想法是我想 cd 到 ~/marker.sh go $@ 的输出

问题在于 bash 将其解释为一个命令,并给出错误:

-bash: cd: ~/marker.sh go : No such file or directory
-bash: home: command not found

我认为这意味着 shell 将整个别名解析为字符串。

我已经尝试了对别名 $()、`` 等的 shell 脚本部分的各种形式的引用,但它们要么尝试在 bash 启动时运行脚本,要么根本不执行而只保留一个字符串。

我编写这个主要是为了学习 bash 命令,但我无法弄清楚这一部分!

我在 iTerm 1.0.0.20130624 中运行 OSX 10.9,如果这很重要的话。

编辑:我理解cd-ing inside a script won't work,这就是为什么我试图使用我的程序返回正确的路径并使用内置的别名系统来进行目录的实际更改。

【问题讨论】:

  • 对了,你看过bash的目录栈特性,特别是popdpushd命令吗?
  • 就像我说的,我对 bash 脚本非常陌生。我现在就去看看!
  • 它们与您尝试执行的操作非常相似,尽管您正在实现目录的哈希表,而不是堆栈。
  • 是的 - 我想要一个哈希表。我还存储了哈希表(实际上在不同的脚本中使用了 python 字典),然后将 dict 作为平面文件存储在我的硬盘上,这样我就可以使用常用目录的自定义名称在我的操作系统上跳转。

标签: linux macos bash shell alias


【解决方案1】:

你想要一个函数,而不是别名:

place () {
    cd $( ~/marker.sh go "$@" )
}

别名不带参数;它们只是就地扩展,参数出现在别名扩展为之后。

(你应该总是更喜欢一个函数而不是别名,除非这个函数不能适应你想要的。)

【讨论】:

  • 啊,好吧——但是我如何获得修改主 shell 范围的函数——也就是说,实际上改变我的工作目录,而不是仅仅在这个函数中 cd-ing 然后返回我的我当前的工作目录?我应该把这个脚本放在哪里?
  • 这个函数会修改调用它的shell的工作目录。由您来确保 place 是由您当前的 shell 调用的,而不是在没有来源的脚本中。
  • 啊,好吧。谢谢!我现在要试试这个。
【解决方案2】:

使用函数,而不是别名或外部 bash 脚本!

在您的 .bashrc 或其来源的任何文件中,或您将手动来源的任何文件中,放置这个完全可用的脚本!

declare -A _mark_dir_hash

mark() {
   [[ -z $1 ]] && { listmarks; return 0; }
   if [[ -n ${_mark_dir_hash[$1]} ]] && [[ $1 != ${_mark_dir_hash[$1]} ]]; then
       echo "Mark $1 was already set to ${_mark_dir_hash[$1]}... replaced with new mark"
   fi
   _mark_dir_hash[$1]=$(pwd)
}

place() {
   [[ -z $1 ]] && { echo >&2 "You must give a mark name to go to!"; return 1; }
   [[ -z ${_mark_dir_hash[$1]} ]] && { echo >&2 "Mark $1 unknown!"; return 1; }
   cd "${_mark_dir_hash[$1]}"
}

listmarks() {
   [[ -z ${!_mark_dir_hash[@]} ]] && { echo "No marks!"; return 0; }
   for i in "${!_mark_dir_hash[@]}"; do
      printf '%s --> %s\n' "$i" "${!_mark_dir_hash[@]}"
   done
}

removemark() {
   [[ -z $1 ]] && { echo >&2 "You must give a mark name to remove!"; return 1; }
   unset _mark_dir_hash[$1]
}

clearmarks() {
   _mark_dir_hash=()
}

哈,我刚刚意识到您使用的是 Mac,因此您可能会被不支持关联数组的老式 bash 版本卡住。对你太坏了。然而,这可能对使用现代 shell 的其他人有用!

【讨论】:

  • 非常酷的实现!我只是将繁重的工作外包给一个 python 程序,因为我更熟悉它,并使用 bash 函数连接到它。
  • 我认为这里唯一的区别是您的版本不会保存到磁盘(以便标记跨会话保存)。
  • 仍然,+1 写这一切:D
  • 我在 Mac OS X 上使用 4.2.45 版本的 Bash 和 GNU 版本的主要 shell 命令(所有 coreutils、sed、awk、grep...)。这不是默认配置,但这很容易;)
猜你喜欢
  • 1970-01-01
  • 2014-08-02
  • 2020-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-18
  • 2013-12-02
  • 1970-01-01
相关资源
最近更新 更多