有没有一种方法可以快速将目录更改为其中一个作业正在运行的目录?

有没有一种方法可以快速将目录更改为其中一个作业正在运行的目录?

的输出jobs看起来像这样

[1]   Stopped                 TERM=xterm-256color vim --servername vim ~/.gitconfig
[2]-  Stopped                 TERM=xterm-256color vim --servername vim ~/.vimrc  (wd: ~)
[3]+  Stopped                 TERM=xterm-256color vim --servername vim i3blocks.conf  (wd: ~/.config/i3/configs)

其中该部分(如果存在)显示(wd: path)path相应作业启动的目录。

有好几次我想搬到那个目录去从事其中一项工作。

有这样做的实用程序吗?

答案1

在 中zsh$jobdirs关联数组将作业编号映射到它们启动的工作目录,因此您可以cd $jobdirs[n]进入cd作业 n 的目录(或者cd ${jobdirs[n]?}如果作业不存在,则得到一个错误而不是带您回家)。

~$ jobs -d
[1]  - running    sleep 1000
(pwd : /tmp)
[2]  + suspended  sleep 123123
(pwd : /usr/local)
~$ cd $jobdirs[2]
/usr/local$

另请参阅$jobstates$jobtexts关联数组以了解每个作业的状态和代码。

在 中bash,您唯一的选择是解析作业的输出,不幸的是,这只能通过启发式方法来完成。例如,参见:

bash-5.1$ mkdir ') (wd: blah blah)
[5] (wd: blah blih)
'
bash-5.1$ cd ') (wd: blah blah)
[5] (wd: blah blih)
'
bash-5.1$ sh -c 'sleep inf' '(wd: /etc)
[2] (wd: bloh bloh)
'
^Z
[1]+  Stopped                 sh -c 'sleep inf' '(wd: /etc)
[2] (wd: bloh bloh)
'
bash-5.1$ jobs 1
[1]+  Stopped                 sh -c 'sleep inf' '(wd: /etc)
[2] (wd: bloh bloh)
'
bash-5.1$ cd /
bash-5.1$ jobs 1
[1]+  Stopped                 sh -c 'sleep inf' '(wd: /etc)
[2] (wd: bloh bloh)
'  (wd: ~/1/) (wd: blah blah)
[5] (wd: blah blih)
)

您可以看到,(wd:...)仅当作业的目录不是当前工作目录时才会打印 ,并且如果作业的命令行或工作目录恰好包含 s ,则(wd: ...) 无法判断哪个(wd:s 是实际工作目录的开头。

还将您的主目录替换为~.

还要注意它wd:是本地化的。例如,用乌克兰语:

bash-5.1$ LC_ALL=uk_UA.utf8 jobs 1
[1]+  Зупинено        sh -c 'sleep inf' '(wd: /etc)
[2] (wd: bloh bloh)
'  (РД: ~/1/) (wd: blah blah)
[5] (wd: blah blih)
)

因此,您需要确保jobs在您期望相应的语言环境中调用工作目录缩写。

你所能做的就是使用启发式方法并希望得到最好的结果:

cdj() {
  local dir
  dir=$(LC_ALL=C jobs -- "$1") || return
  case $dir in
    (*'(wd:'*')')
      dir=${dir%')'}
      dir=${dir##*'(wd: '}
      case $dir in
        ('~'*) dir=$HOME${dir#'~'}
      esac
      printf >&2 '%s\n' "Job $1's dir is likely \"$dir\""
      cd -- "$dir";;
    (*)
      printf >&2 '%s\n' "Job $1's dir is likely the current directory already"
  esac
}

这在我们上面设计的示例中失败了,但在大多数正常情况下应该可以工作。

答案2

现在,我已经解决了在我的中定义以下函数的问题~/.bashrc

cdj () {
  jobNumber="$1"
  dir="$(jobs | grep "^\[$jobNumber\]" | sed 's/.*(wd: \(.*\))/\1/;t;d')"
  [[ -n "$dir" ]] && eval "cd $dir"
}

这样我就可以执行此操作,如果我传递不存在的作业或从当前目录运行的作业的编号,则(故意)失败。cd job-number

相关内容