我经常考虑赞扬zsh的帖子,因此正在考虑从bash迁移到zsh。我是一位经验丰富的命令行用户,我假设基本知识几乎相同,因此我正在寻找建议,以获取移动带来的好处以及任何需要注意的问题。

请仅对每个答案给出一点建议。我正在寻找一口大小的块,以便可以返回并将稳定的步伐将更多的信息集成到我的shell使用中,而不是一口气尝试全部学习。

评论

我很想知道是否可以将Ubuntu的Command-not-Found与zsh集成在一起。由于这个原因(以及其他许多烦恼),我改回了bash。

其他Stack Exchange网站上的相关线程:是否值得随便使用zsh?您的.zshrc中有什么?您使用什么zsh功能? bash与zsh相比的独特功能是否有理由在zsh上使用bash? zsh中有哪些功能,bash缺少这些功能,反之亦然?

另外两个有趣的链接:“ ZSH常见问题解答” zsh.sourceforge.net/FAQ和“ ZSH是您的朋友” mikegrouchy.com/blog/zsh-is-your-friend.html

@MariusGedminas :(从这里开始)zsh支持此功能,但是您必须手动启用它。只需将源代码/ etc / zsh_command_not_found添加到您的.zshrc中。

command-not-found是一个zsh插件

#1 楼

如您所说,zsh在许多方面都与bash相似。它具有您在bash中找不到的某些功能,并且可以通过强大的方式进行扩展。不要将移动视为一种革命,而应将其视为一系列对您的日常工作有所帮助的进化步骤。这是我的.zshrc的一些提示。尽管您说您更喜欢单条建议,但该帖子是冗长的清单。仍然要逐一讨论这些观点,这是一个好主意。只需将有趣的位添加到您的~/.zshrc并重新加载source ~/.zshrc即可。最后提示:了解zsh的默认(“ Emacs”)键盘快捷键:^A ^E ^W Alt-F Alt-B Alt-P ^L ^R的击键。您可以通过两个单独的击键来替换AltAlt-P等同于ESC P


这将为您提供更广泛的制表符完成。

autoload -U compinit
compinit

< br两端的制表符完成。

setopt completeinword


制表符完成不区分大小写。

zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}'


>更好地完成killall。

zstyle ':completion:*:killall:*' command 'ps -u $USER -o cmd'


更改“单词”的定义,例如带^ W。

autoload select-word-style
select-word-style shell


ls的颜色。

if [[ -x "`whence -p dircolors`" ]]; then
  eval `dircolors`
  alias ls='ls -F --color=auto'
else
  alias ls='ls -F'
fi


ls的快捷方式。

alias ll='ls -l'
alias la='ls -a'


所有开放壳的历史记录;存储10,000个条目。这使它成为有用的内存辅助工具,以查找您上次用于./configure等的命令。自由使用Alt-P(这样开始的查找命令)和^ R(在历史中搜索)。

HISTFILE=~/.zhistory
HISTSIZE=SAVEHIST=10000
setopt sharehistory
setopt extendedhistory


启用各种扩展的glob,例如ls ** / *。txt(查找所有文本文件),ls -d *(D)(显示所有文件,包括以“。”开头的文件)。要了解更多信息,请转到man zshexpn的“文件名生成”部分。

# superglobs
setopt extendedglob
unsetopt caseglob


这对记住历史记录中的命令而不执行它们很有用。

setopt interactivecomments # pound sign in interactive prompt


键入“ ..”代替“ cd ..”,用“ / usr / include”代替“ cd / usr / include”。

setopt auto_cd


很好的提示。

PS1='[%T] %n@%m:%~# '


显示耗时超过10秒的命令的CPU使用情况统计信息

REPORTTIME=10


某些命令您可以在Ubuntu中广泛使用。

alias 'a=sudo aptitude'
alias 'ai=sudo aptitude install'
alias 'ar=sudo aptitude remove'
alias 'au=sudo aptitude update'
alias 'ag=sudo aptitude safe-upgrade'
alias 'as=apt-cache search'
alias 'aw=apt-cache show'


列出按大小排序的软件包-在确定哪些软件包占用了磁盘空间时很有用。

function apt-list-packages {
  dpkg-query -W --showformat='${Installed-Size} ${Package} ${Status}\n' | grep -v deinstall | sort -n | awk '{print " "}'
}


评论


+1是有用的。 -1为秘密的emacs宣传!

–三联画
2013年11月20日15:30

您可能还喜欢[github.com/robbyrussell/oh-my-zsh](oh-my-zsh),它向zsh添加了许多插件。

– RedPixel
2014年7月22日在6:58

#2 楼

我会推荐《从bash到Z Shell》这本书。它提供了切换外壳所需的所有建议。它说明了两个外壳的区别,并简化了新zsher的操作。

评论


这本书对bash和zsh用户都非常有用。您一定喜欢每个章节都以“ bash和zsh都可以完成这一切”开头,然后又引出了30页“这是zsh唯一的东西”

–里克
2010年9月3日,下午1:54

#3 楼

这是我的.zshrc,这是最重要的事情! zsh有很多可用的选项,因此请看一下网上的所有示例或阅读Zsh主页上的文档。

我的.zshrc不含任何其他非常酷的东西而不是命令行右侧的时间戳。

请记住,请尝试在每个示例中使用制表符补全:

mplayer -a[tab]


将显示以下内容:

mplayer -a
 -ac                 -- force usage of a specific audio codec
 -af                 -- activate audio filters
 -afm                -- force usage of a specific audio codec family
 -alang              -- select the DVD audio language
 -ao                 -- specify audio driver
 -aop                -- specify audio output filter


如果使用无密码的ssh-key或ssh-agent,您可能会发现使用Tab键完成远程文件很有用:

scp apollo:/home/user/[tab]
Desktop/ Documents/ Downloads/ Music/ Pictures/ Public/ Templates/ Videos/


获取列表后,您可以按Tab键多次以浏览不同的可能性。

但请注意,此外壳会让您懒惰并让您感觉到标准外壳是愚蠢而烦人的!

#4 楼

几个特别有用的扩展glob:


rmdir *(/^F)-删除当前目录下的所有非空目录
grep traceback /srv/log/**/*(.m-2)-在最近两天修改的文件中查找此正则表达式
chmod g+w **/*(U^I)-将我拥有的但不是组可写的所有文件都设置为组可写。

是的,您当然可以使用find编写此文件,但这更容易折断。公平地说,它确实有两个缺点,这两个缺点都是将它们都扩展到了命令行上:如果它与成千上万个文件匹配,则命令行将变得太长,这将失败,其次,将找到所有文件在文件开始运行之前。

(如果尚未启用,则需要setopt extendedglob

#5 楼

我对bash不太了解,所以我无法忍受。我的zsh配置文件中的一些代码片段。

一些配置

HISTFILE=~/.zsh_history
HISTSIZE=1000
SAVEHIST=1000
REPORTTIME=10 # print elapsed time when more than 10 seconds
setopt NO_HUP
setopt NO_LIST_BEEP
setopt LOCAL_OPTIONS # allow functions to have local options
setopt LOCAL_TRAPS # allow functions to have local traps
setopt HIST_VERIFY
setopt SHARE_HISTORY # share history between sessions ???
setopt EXTENDED_HISTORY # add timestamps to history
setopt PROMPT_SUBST
setopt CORRECT
setopt COMPLETE_IN_WORD
setopt IGNORE_EOF

setopt APPEND_HISTORY # adds history
setopt INC_APPEND_HISTORY SHARE_HISTORY  # adds history incrementally and share it across sessions
setopt HIST_IGNORE_ALL_DUPS  # don't record dupes in history
setopt HIST_REDUCE_BLANKS
# Leave some chars out of the out of WORDCHARS so ^W acts more nicely 
WORDCHARS='*?_-[]~\!#$%^(){}<>|`@#$%^*()+:?'


在提示符下Git

if [[ -n $SSH_CONNECTION ]]; then
  export PS1='%m:%3~$(git_info_for_prompt)%# '
else
  export PS1='%3~$(git_info_for_prompt)%# '
fi


一些热键,在该行的开头插入一些文本。

insert_sudo     () { zle beginning-of-line; zle -U "sudo "         }
insert_apt      () { zle beginning-of-line; zle -U "sudo apt-get " }
insert_gem      () { zle beginning-of-line; zle -U "sudo gem "     }
insert_install  () { zle -U "install "     }

zle -N insert-sudo      insert_sudo
zle -N insert-apt       insert_apt
zle -N insert-gem       insert_gem
zle -N insert-install   insert_install

bindkey "^B" insert-gem
bindkey "^N" insert-install
bindkey "^k" insert-sudo
bindkey "^a" insert-apt


函数,然后将它们存储在〜/ .zsh / functions

git_info_for_prompt

local g="$(git rev-parse --git-dir 2>/dev/null)"
if [ -n "$g" ]; then
  local r
  local b
  if [ -d "$g/../.dotest" ]
  then
    if test -f "$g/../.dotest/rebasing"
    then
      r="|REBASE"
    elif test -f "$g/../.dotest/applying"
    then
      r="|AM"
    else
      r="|AM/REBASE"
    fi
    b="$(git symbolic-ref HEAD 2>/dev/null)"
  elif [ -f "$g/.dotest-merge/interactive" ]
  then
    r="|REBASE-i"
    b="$(cat "$g/.dotest-merge/head-name")"
  elif [ -d "$g/.dotest-merge" ]
  then
    r="|REBASE-m"
    b="$(cat "$g/.dotest-merge/head-name")"
  elif [ -f "$g/MERGE_HEAD" ]
  then
    r="|MERGING"
    b="$(git symbolic-ref HEAD 2>/dev/null)"
  else
    if [ -f "$g/BISECT_LOG" ]
    then
      r="|BISECTING"
    fi
    if ! b="$(git symbolic-ref HEAD 2>/dev/null)"
    then
      if ! b="tag: $(git describe --exact-match HEAD 2>/dev/null)"
      then
        b="$(cut -c1-7 "$g/HEAD")..."
      fi
    fi
  fi

  if [ -n "" ]; then
    printf "" "${b##refs/heads/}$r"
  else
    printf "[%s]" "${b##refs/heads/}$r"
  fi
fi


一些github选项

#compdef github

_github() {
  if (( CURRENT > 2 )); then
    # shift words so _arguments doesn't have to be concerned with second command
    (( CURRENT-- ))
    shift words
    # use _call_function here in case it doesn't exist
    _call_function 1 _github_${words[1]}
  else
    _values "github command" \
     "fetch[Fetch from a remote to a local branch.]" \
     "ignore[Ignore a SHA (from 'github network commits')]" \
     "fetch_all[Fetch all refs from a user]" \
     "info[Info about this project.]" \
     "browse[Open this repo in a web browser.]" \
     "home[Open this repo's master branch in a web browser.]" \
     "clone[Clone a repo.]" \
     "pull-request[Generate the text for a pull request.]" \
     "network[Project network tools.]" \
     "pull[Pull from a remote.]" \
     "track[Track another user's repository.]"
  fi
}

_github_pull() {
  _arguments \
    "--merge[Automatically merge remote's changes into your master.]"
}
_github_clone() {
  _arguments \
    "--ssh[Clone using the git@github.com style url.]"
}

_github_track() {
  _arguments \
    "--private[Use git@github.com: instead of git://github.com/.]" \
    "--ssh[Equivalent to --private.]"
}

_github_network() {
  if (( CURRENT > 2 )); then
    # shift words so _arguments doesn't have to be concerned with second command
    (( CURRENT-- ))
    shift words
    # use _call_function here in case it doesn't exist
    _call_function 1 _github_network_${words[1]}
  else
    _values "github network command" \
     "web[Open network in a web browser.]" \
     "list[List networked repositories.]" \
     "fetch[Fetched commits for a given networked repository.]" \
     "commits[List networked commits not pulled into this repo.]"
  fi
}

_github_network_commits() {
  _arguments \
    "--project[Filter commits on a certain project.]" \
    "--author[Filter commits on a email address of author.]" \
    "--common[Show common branch point.]" \
    "--nocache[Do not use the cached network data.]" \
    "--sort[How to sort : date(*), branch, author.]" \
    "--thisbranch[Look at branches that match the current one]" \
    "--applies[Filter commits to patches that apply cleanly.]" \
    "--limit[Only look through the first X heads - useful for really large projects]" \
    "--before[Only show commits before a certain date.]" \
    "--after[Only show commits after a certain date.]" \
    "--shas[Only show shas.]" \
    "--cache[Use the network data even if it's expired.]" \
    "--noapply[Filter commits to patches that do not apply cleanly.]"
}


#6 楼

我在同一趟旅程中:)

到目前为止,我发现问题是要拥有一个好的配置文件(.zshrc)。

把这个作为例如http://matt.blissett.me.uk/linux/zsh/zshrc,请查看注释并破解您的方法。 Stackoverflow和severphault也是搜索的好地方。 />

#7 楼

了解有关zsh中扩展的glob和递归glob的信息。

了解有关zstyle的知识,以及各种方法(尤其是完成方法)如何使您使用zstyle调整其配置。

了解一下关联数组。还有标准数组(请注意与bash的区别,以求更好!)

如果您使用正则表达式,请查看=~(bash也具有此表达式)并考虑:setopt rematch_pcre

避免编写依赖于zsh魔法多的脚本,因为尽管使用起来很棒,但zsh倾向于只写。如果使用过多,请考虑何时切换到Python之类的语言。

Zsh很诱人。这是阴暗的一面。欢迎您。

#8 楼

巨大的好处–出色的制表符补全功能以及针对许多命令的预打包补全脚本。这是显示apt-get<TAB>输出的示例:

apt-get
action
autoclean        build-dep        clean            dselect-upgrade  install          remove           update           
autoremove       check            dist-upgrade     help             purge            source           upgrade          


#9 楼

我提供了一场讨论,并将几个人转换为zsh。我在这里保存了我的笔记(有什么好处)的github仓库以及启动器和我自己的zsh配置的副本。

http://github.com/mitechie/zshrc

#10 楼

另一个很棒的资源是zsh爱好者页面(来自grml zsh网站)。