切换到zsh shell后,“ls”命令会结束终端标签页。

3
我正在从Fish Shell转换到Zsh。
我刚刚经历了一个漫长的过程,将我的一堆Fish函数转换成Zsh,大部分都能正常工作,但我刚刚注意到,当我输入“ls”时,它不仅无法工作,而且实际上会结束终端选项卡会话。
➜  ~  cd code
➜  code  ls

[Process completed]

超级困惑,因为我没有(我不认为)做任何与该命令有关的事情。大多数其他基本命令似乎都可以正常工作。有什么想法可能会导致这种混乱吗?我已经在下面放置了我的新Zsh函数和.zshrc文件。
这些函数大多是一堆Git / Zeus(Rails工具)函数,使我的生活更轻松:
~/.oh-my-zsh/custom/plugins/functions/functions.plugin.zsh
##############################
######### ZEUS BASED #########
##############################

z () zeus start

rmz () rm .zeus.sock

rr () {
  if [ "$#" -gt 0 ]; then
    r routes | grep "$@" 
  else
    r routes
  fi
}

zeus_on () {
  if ps aux | grep -v grep | grep 'zeus slave: development_environment'; then
    true
  else
    false
  fi
}

mg () r db:migrate "$@"

tprep () {
  if zeus_on; then
    zeus rake db:test:prepare "$@"
  else
    echo "Zeus is not running"
    rake db:test:prepare "$@"
  fi
}

s () { 
  if zeus_on; then
    zeus s
  else
    echo "Zeus is not running"
    rails s
  fi
}

t () {
  if zeus_on; then
    if [ '$#' -gt 0 ]; then
      zeus test "$@"
    else
      zeus test spec
    fi
  else
    echo "Zeus is not running"
    if [ "$#" -gt 0 ]; then
      rspec "$@"
    else
      rspec spec
    fi
  fi
}

tt () zeus rspec --tag $1 spec

r () {
  if zeus_on; then
    zeus rake "$@"
  else
    echo "Zeus is not running"
    rake "$@"
  fi
}

c () {
  if zeus_on; then
    zeus c "$@"
  else
    echo "Zeus is not running"
    rails c "$@"
  fi
}

jt () {
  if zeus_on; then
    if [ "$#" -gt 0 ]; then
      zeus tr spec:javascript SPEC="$@"
    else
      zeus tr spec:javascript
    fi
  else
    echo "Zeus is not running"
    if [ "$#" -gt 0 ]; then
      rake spec:javascript RAILS_ENV=test SPEC="$@"
    else
      rake spec:javascript RAILS_ENV=test
    fi
  fi
}

# ##############################
# ############ GIT #############
# ##############################

gcurrent () git rev-parse --abbrev-ref HEAD

gclean! () git clean -f -d

gd () git diff "$@"

gds () git diff --staged "$@"

gdh () git diff HEAD^

gr () git rebase "$@"

gri () gr -i "$@"

grc () gr --continue

gback () git reset HEAD^

gh () hub browse

gac () {
  ga
  gc "$@"
}

gacm () gac -m "$@"

ga () {
  if [ "$#" -gt 0 ]; then
    git add "$@"
  else
    git add .
  fi
}

gp () git pull "$@"

gs () git status "$@"

gsp () git stash pop

gss () git stash save

gl () git log --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit "$@"

gco () git checkout "$@"

gcom () git checkout master

gpush () git push "$@"

gb () git branch "$@"

gbd () git branch -d "$@"

gc () git commit "$@"

gca () gc --amend

grb () git rebase "$@"

g () git "$@"

gcpick () git cherry-pick "$@"

grh () git reset --hard "$@"

gbdelete () git push origin --delete "$@"


# ###############################
# ######## CD SHORTCUTS #########
# ###############################

fish_dir () cd ~/.config/fish/

# Define code_directory in .zshrc
code () cd /$code_directory/"$@"

f () code "$@"

# ##############################
# ########### OTHER ############
# ##############################


tasks () ps aux | grep $@

b () bundle $@

ll () ls -lh $@

fs () foreman start $@

hcon () heroku run rails console

dtest () tail -f diagnostic.txt

sb () {
  if [ "$#" -gt 0 ]; then
    sublime "$@"
  else
    sublime .
  fi
}

fish_edit () {
  sb ~/.config/fish/config.fish
}

可能与此无关,但对我也很困惑。当我在相关文件中打开一个新的shell tab时,会收到有关使用grep的警告。以前Fish没有出现过这种情况:

usage: grep [-abcDEFGHhIiJLlmnOoqRSsUVvwxZ] [-A num] [-B num] [-C[num]]
  [-e pattern] [-f file] [--binary-files=value] [--color=when]
  [--context[=num]] [--directories=action] [--label] [--line-buffered]
  [--null] [pattern] [file ...]

最后,需要导入这些插件的.zshrc文件。 这个答案(尽管行为不同)表明可能是PATH定义问题,但我认为我在我的PATH中包含了所有必要的路径:

# Path to your oh-my-zsh installation.
export ZSH=$HOME/.oh-my-zsh

export code_directory=$HOME/code/

ZSH_THEME="robbyrussell"

plugins=(functions github)

# User configuration

export PATH="/Users/sasha/.rvm/gems/ruby-2.2.0/bin:/Users/sasha/.rvm/gems/ruby-2.2.0@global/bin:/Users/sasha/.rvm/rubies/ruby-2.2.0/bin:/Users/sasha/.rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/git/bin"
# export MANPATH="/usr/local/man:$MANPATH"

source $ZSH/oh-my-zsh.sh

回答以下问题:

➜  .oh-my-zsh git:(master) ✗ which ls
ls: aliased to ls -G
➜  .oh-my-zsh git:(master) ✗ typeset -f ls
ls () {
    ls -G -lh $@
}
➜  .oh-my-zsh git:(master) ✗ type ls
ls is an alias for ls -G

更新

我已经找出了导致这个问题的原因,但不知道为什么会出现这个问题。问题出在这一行代码:

ll () ls -lh $@

在我的函数文件中,我想当我键入ll时运行ls -lh whatever-arguments-follow。为什么当我运行ls时会出现错误?


1
which lstypeset -f lstype ls 会输出什么? - Jens
在上面已经回答了 - 看起来它被别名化了?我会找到那个地方,但我不明白为什么ls -G会破坏终端标签。 - Sasha
1
这可能是由于ls的递归(无限)定义引起的吗?如果将ls别名为/bin/ls -G会发生什么? - bdesham
找到了导致问题的原因,但不知道为什么。请参见上文更新。 - Sasha
1
尝试在子shell中输入“ls”,即运行“zsh”,然后在“zsh”提示符处键入“ls”。如果“zsh”在关闭时打印错误消息,这应该让您在选项卡关闭之前看到它(并带您回到父shell)。 - Keith Thompson
显示剩余3条评论
1个回答

3

好的,所以ls既是别名又是函数。这不会起作用,因为它们会递归。在我的终端上,当ls是别名和函数时,当我运行

ls

它思考了两秒钟,然后我得到了结果。

ls:1: maximum nested function level reached

请使用函数或别名中的一个,而不是两者同时使用。

编辑 哦,看起来那样可能行得通,但问题在于ls函数是递归的。应该这样写:

ls () {
    command ls -G -lh $@
}
command 内置命令可以确保你执行的是实际的命令,而不是别名或函数。

我不知道我是在将它定义为别名还是函数。我已经定义了一个“ll”函数。这是否隐式地将“ls”设置为别名或其他内容? - Sasha
1
有人已经做了这件事。也许你的zsh配置文件会源于/etc/profile/etc/zsh/etc/zshrc等等。你是否设置了ENV变量? - Jens
超级奇怪,我根本没有 ls 函数。只有 ll,它应该直接调用 ls。但是当我添加了 command 后,它既可以工作,而且还替换了 llls 为同一个函数(基本上是我创建 ll 的目的)。再次声明,我没有在任何地方重新定义 ls,但看起来 ll 在某种程度上正在递归重新定义它!?!(我唯一的代码在上面的问题中)。有什么想法吗? - Sasha
只是将我的 ll 方法重命名为 lol 就完全解决了问题。(这样 lsll 都能以它们各自正确的方式工作)。很奇怪。我再仔细查看了一下,似乎已经在某个地方定义了一个 ll 函数,重新定义它导致了问题。 - Sasha
1
@Sasha 如果你想详细了解zsh作为登录shell启动时的操作,可以运行zsh -l -x。这将最终提供线索,指出别名和函数的来源。 - Jens
1
请注意,使用“type ll”可以查看正在使用的ll(例如别名或shell函数),而“whence -f ll”则显示其定义。这可能会给你一些线索,告诉你它是在哪里定义的。 - user1934428

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接