[分享]终极Shell——Zsh

仅仅用于软件推荐,不适合发求软件或软件使用问题方面的贴子
回复

心动VS行动?

行动
87
44%
心动
21
11%
以静制动
91
46%
 
总计票数: 199
kardinal
帖子: 750
注册时间: 2006-03-19 11:39

[分享]终极Shell——Zsh

#1

帖子 kardinal » 2008-07-26 20:55

有句话这样说
zsh: The last shell you’ll ever need!
Z是最后一个字母,所以是终极Shell

我曾经搜索到一个比较各种Shell的文章
Zsh交互性是A+级别的,远高于其它Shell
在编程方面,Zsh是A级的吧,也是最高的
只是不知道出于什么原因,Zsh被严重的低估了
大多数的Linux用户比较偏爱Bash,因为大多数的发行版默认的就是它
凭心而论,Bash确实比Csh之流的好用多了 :lol:

不过Bash也有很多地方不尽人意,像自动补全的功能不够强大,定位较长路径不够方便等

后来我使用Zsh。如果不调整一些必要的配置的话,Zsh甚至还不如Bash好用
这也是很多人尝试过并放弃过的原因

不熟悉Zsh的人,对Zsh最深刻的印象应该就是它的命令提示符了
它支持右侧对齐的提示符,并且可以配置成这个样子的
图片
不过我还是喜欢比较简单的样式

Zsh的自动补全功能十分的强大,如图所示
它可以自动补全命令、参数、文件名、进程、用户名、变量、权限符等
图片

Zsh还有一个贴心的功能:路径别名
假设有一个很长的路径,例如/home/lighttpd/html
可以把这个路径命名为 ~WWW
图片

Zsh可以使用Emacs风格的键绑定,习惯Bash键绑定的朋友无需重新适应
Zsh兼容大多数主流Shell,像Bash、Csh等
附件
1.GIF
1.GIF (8.47 KiB) 查看 28027 次
2.GIF
3.GIF
上次由 kardinal 在 2009-01-11 16:32,总共编辑 33 次。
kardinal
帖子: 750
注册时间: 2006-03-19 11:39

#2

帖子 kardinal » 2008-07-26 20:58

配置文件

代码: 全选

#color{{{
autoload colors zsh/terminfo
if [[ "$terminfo[colors]" -ge 8 ]]; then
colors
fi
for color in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE; do
eval _$color='%{$terminfo[bold]$fg[${(L)color}]%}'
eval $color='%{$fg[${(L)color}]%}'
(( count = $count + 1 ))
done
FINISH="%{$terminfo[sgr0]%}"
#}}}

#命令提示符 {{{
precmd () {
local count_db_wth_char=${#${${(%):-%/}//[[:ascii:]]/}}
local leftsize=${#${(%):-%M%/}}+$count_db_wth_char
local rightsize=${#${(%):-%D %T }}
HBAR=" -"
 
FILLBAR="\${(l.(($COLUMNS - ($leftsize + $rightsize +2)))..${HBAR}.)}"
 
RPROMPT=$(echo "%(?..$RED%?$FINISH)")
PROMPT=$(echo "$BLUE%M$GREEN%/ $WHITE${(e)FILLBAR} $MAGENTA%D %T$FINISH
$CYAN%n $_YELLOW>>>$FINISH ")
 
#在 Emacs终端 中使用 Zsh 的一些设置
if [[ "$TERM" == "dumb" ]]; then
setopt No_zle
PROMPT='%n@%M %/
>>'
alias ls='ls -F'
fi 	
}
#}}}

#标题栏、任务栏样式{{{
case $TERM in (*xterm*|*rxvt*|(dt|k|E)term)
   preexec () { print -Pn "\e]0;%n@%M//%/\ $1\a" }
   ;;
esac
#}}}

#关于历史纪录的配置 {{{
#历史纪录条目数量
export HISTSIZE=10000
#注销后保存的历史纪录条目数量
export SAVEHIST=10000
#历史纪录文件
#export HISTFILE=~/.zhistory
#以附加的方式写入历史纪录
setopt INC_APPEND_HISTORY
#如果连续输入的命令相同,历史纪录中只保留一个
setopt HIST_IGNORE_DUPS      
#为历史纪录中的命令添加时间戳      
setopt EXTENDED_HISTORY      
 
#启用 cd 命令的历史纪录,cd -[TAB]进入历史路径
setopt AUTO_PUSHD
#相同的历史路径只保留一个
setopt PUSHD_IGNORE_DUPS
 
#在命令前添加空格,不将此命令添加到纪录文件中
#setopt HIST_IGNORE_SPACE      
#}}}

#每个目录使用独立的历史纪录{{{
HISTDIR="$HOME/.zhistory"
    [[ ! -d "$HISTDIR" ]] && mkdir -p "$HISTDIR"
HISTFILE="$HISTDIR/${PWD//\//:}"
chpwd() {
#   fc -W                                       # write current history  file
#   "setopt INC_APPEND_HISTORY"
    HISTFILE="$HISTDIR/${PWD//\//:}"            # set new history file
    [[ ! -e "$HISTFILE" ]] && touch $HISTFILE
    local ohistsize=$HISTSIZE
        HISTSIZE=0                              # Discard previous dir's history
        HISTSIZE=$ohistsize                     # Prepare for new dir's history
    fc -R                                       # read from current histfile
}
 
function allhistory { cat $HISTDIR/* }                                   #*/
function convhistory {
            sort $1 | sed 's/^:\([ 0-9]*\):[0-9]*;\(.*\)/\1::::::\2/' |
            awk -F"::::::" '{ $1=strftime("%Y-%m-%d %T",$1) "|"; print }'  
}
#使用 histall 命令查看全部历史纪录
function histall { convhistory =(allhistory) |
            sed '/^.\{20\} *cd/i\\' }
#使用 hist 查看当前目录历史纪录
function hist { convhistory $HISTFILE }
 
#全部历史纪录 top55
function top55 { allhistory | awk -F':[ 0-9]*:[0-9]*;' '{ $1="" ; print }' | sed 's/ /\n/g' | sed '/^$/d' | sort | uniq -c | sort -nr | head -n 55 }
 
#}}}

#杂项 {{{
#允许在交互模式中使用注释  例如:
#cmd #这是注释
setopt INTERACTIVE_COMMENTS      
 
#启用自动 cd,输入目录名回车进入目录
#稍微有点混乱,不如 cd 补全实用
#setopt AUTO_CD
      
#扩展路径
#/v/c/p/p => /var/cache/pacman/pkg
setopt complete_in_word
 
#禁用 core dumps
limit coredumpsize 0
 
#Emacs风格 键绑定
bindkey -e
#设置 [DEL]键 为向后删除
bindkey "\e[3~" delete-char
 
#以下字符视为单词的一部分
WORDCHARS='*?_-[]~=&;!#$%^(){}<>'
#}}}

#自动补全功能 {{{
setopt AUTO_LIST
setopt AUTO_MENU
#开启此选项,补全时会直接选中菜单项
#setopt MENU_COMPLETE

autoload -U compinit
compinit
 
#自动补全缓存
#zstyle ':completion::complete:*' use-cache on
#zstyle ':completion::complete:*' cache-path .zcache
#zstyle ':completion:*:cd:*' ignore-parents parent pwd

#自动补全选项
zstyle ':completion:*' verbose yes
zstyle ':completion:*' menu select
zstyle ':completion:*:*:default' force-list always
zstyle ':completion:*' select-prompt '%SSelect:  lines: %L  matches: %M  [%p]'
 
zstyle ':completion:*:match:*' original only
zstyle ':completion::prefix-1:*' completer _complete
zstyle ':completion:predict:*' completer _complete
zstyle ':completion:incremental:*' completer _complete _correct
zstyle ':completion:*' completer _complete _prefix _correct _prefix _match _approximate
 
#路径补全
zstyle ':completion:*' expand 'yes'
zstyle ':completion:*' squeeze-slashes 'yes'
zstyle ':completion::complete:*' '\\'
 
#彩色补全菜单 
eval $(dircolors -b) 
export ZLSCOLORS="${LS_COLORS}"
zmodload zsh/complist
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31'
 
#修正大小写
zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}'
#错误校正      
zstyle ':completion:*' completer _complete _match _approximate
zstyle ':completion:*:match:*' original only
zstyle ':completion:*:approximate:*' max-errors 1 numeric
 
#kill 命令补全      
compdef pkill=killall
zstyle ':completion:*:*:kill:*' menu yes select
zstyle ':completion:*:*:*:*:processes' force-list always
zstyle ':completion:*:processes' command 'ps -au$USER'
 
#补全类型提示分组 
zstyle ':completion:*:matches' group 'yes'
zstyle ':completion:*' group-name ''
zstyle ':completion:*:options' description 'yes'
zstyle ':completion:*:options' auto-description '%d'
zstyle ':completion:*:descriptions' format $'\e[01;33m -- %d --\e[0m'
zstyle ':completion:*:messages' format $'\e[01;35m -- %d --\e[0m'
zstyle ':completion:*:warnings' format $'\e[01;31m -- No Matches Found --\e[0m'
zstyle ':completion:*:corrections' format $'\e[01;32m -- %d (errors: %e) --\e[0m'
 
# cd ~ 补全顺序
zstyle ':completion:*:-tilde-:*' group-order 'named-directories' 'path-directories' 'users' 'expand'
#}}}

##行编辑高亮模式 {{{
# Ctrl+@ 设置标记,标记和光标点之间为 region
zle_highlight=(region:bg=magenta #选中区域 
               special:bold      #特殊字符
               isearch:underline)#搜索时使用的关键字
#}}}

##空行(光标在行首)补全 "cd " {{{
user-complete(){
    case $BUFFER in
        "" )                       # 空行填入 "cd "
            BUFFER="cd "
            zle end-of-line
            zle expand-or-complete
            ;;
        "cd  " )                   # TAB + 空格 替换为 "cd ~"
            BUFFER="cd ~"
            zle end-of-line
            zle expand-or-complete
            ;;
        " " )
            BUFFER="!?"
            zle end-of-line
            ;;
        "cd --" )                  # "cd --" 替换为 "cd +"
            BUFFER="cd +"
            zle end-of-line
            zle expand-or-complete
            ;;
        "cd +-" )                  # "cd +-" 替换为 "cd -"
            BUFFER="cd -"
            zle end-of-line
            zle expand-or-complete
            ;;
        * )
            zle expand-or-complete
            ;;
    esac
}
zle -N user-complete
bindkey "\t" user-complete
 
#显示 path-directories ,避免候选项唯一时直接选中
cdpath="/home"
#}}}

##在命令前插入 sudo {{{
#定义功能 
sudo-command-line() {
    [[ -z $BUFFER ]] && zle up-history
    [[ $BUFFER != sudo\ * ]] && BUFFER="sudo $BUFFER"
    zle end-of-line                 #光标移动到行末
}
zle -N sudo-command-line
#定义快捷键为: [Esc] [Esc]
bindkey "\e\e" sudo-command-line
#}}}
  
#命令别名 {{{
alias -g cp='cp -i'
alias -g mv='mv -i'
alias -g rm='rm -i'
alias -g ls='ls -F --color=auto'
alias -g ll='ls -l'
alias -g grep='grep --color=auto'
alias -g ee='emacsclient -t'
alias -g history='history -fi'
 
#[Esc][h] man 当前命令时,显示简短说明 
alias run-help >&/dev/null && unalias run-help
autoload run-help
 
#历史命令 top10
alias top10='print -l  ${(o)history%% *} | uniq -c | sort -nr | head -n 10'
#}}}

#路径别名 {{{
#进入相应的路径时只要 cd ~xxx
hash -d WWW="/home/lighttpd/html"
hash -d ARCH="/mnt/arch"
hash -d PKG="/var/cache/pacman/pkg"
hash -d E="/etc/env.d"
hash -d C="/etc/conf.d"
hash -d I="/etc/rc.d"
hash -d X="/etc/X11"
hash -d BK="/home/r00t/config_bak"
hash -d HIST="$HISTDIR"
#}}}
    
#{{{自定义补全
#补全 ping
zstyle ':completion:*:ping:*' hosts 192.168.128.1{38,} http://www.g.cn \
       192.168.{1,0}.1{{7..9},}
 
#补全 ssh scp sftp 等
my_accounts=(
{r00t,root}@{192.168.1.1,192.168.0.1}
kardinal@linuxtoy.org
123@211.148.131.7
)
zstyle ':completion:*:my-accounts' users-hosts $my_accounts
 
#def pacman-color completion as pacman
compdef pacman-color=pacman
#}}}

#{{{ F1 计算器
arith-eval-echo() {
  LBUFFER="${LBUFFER}echo \$(( "
  RBUFFER=" ))$RBUFFER"
}
zle -N arith-eval-echo
bindkey "^[[11~" arith-eval-echo
#}}}

####{{{
function timeconv { date -d @$1 +"%Y-%m-%d %T" }
 
# }}}

 
## END OF FILE #################################################################
# vim:filetype=zsh foldmethod=marker autoindent expandtab shiftwidth=4
上次由 kardinal 在 2009-06-12 20:48,总共编辑 25 次。
头像
mghohoo
帖子: 364
注册时间: 2008-07-13 18:29
来自: 广州

#3

帖子 mghohoo » 2008-07-26 21:00

lz不要直接粘百度的图片啊,我们是看不到的~
笔记本:Acer 3820tg
台式机:
CPU:Intel E-1230V
内存:32GB RAM
显卡:660GTX
硬盘:INTEL 730 480G
kardinal
帖子: 750
注册时间: 2006-03-19 11:39

#4

帖子 kardinal » 2008-07-26 21:04

好了 把图片作为附件上传了 凑合着看吧 :lol:
头像
solcomo
帖子: 2838
注册时间: 2007-04-25 13:12

#5

帖子 solcomo » 2008-07-26 21:15

代码: 全选

User:~>zsh
/home/user/.zshrc:23: parse error near `}'
$PR_SET_CHARSET$PR_STITLE${(e)PR_TITLEBAR}\ 
$PR_CYAN$PR_SHIFT_IN$PR_ULCORNER$PR_BLUE$PR_HBAR$PR_SHIFT_OUT(\ 
$PR_GREENcomo$PR_GREEN@Lethe:pts/1\ 
$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_CYAN$PR_HBAR${(e)PR_FILLBAR}$PR_BLUE$PR_HBAR$PR_SHIFT_OUT(\ 
$PR_MAGENTAPR_PWDLEN<...<~\ 
$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_CYAN$PR_URCORNER$PR_SHIFT_OUT\ 
$PR_CYAN$PR_SHIFT_IN$PR_LLCORNER$PR_BLUE$PR_HBAR$PR_SHIFT_OUT(\ 
\ 
${(e)PR_APM}$PR_YELLOW21:18\ 
$PR_LIGHT_BLUE:$PR_WHITE%$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT\ 
$PR_CYAN$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT\ 
$PR_NO_COLOUR 
♜♞♝♛♚♝♞♜
♟♟♟♟♟♟♟♟
♙♙♙♙♙♙♙♙
♖♘♗♕♔♗♘♖

☠☯⚔⚓☣☦☃☕
☹☻☪☭☬⚖⚛⚜
ℜℳℬ™ ℋℯℓ℘ ℳℭ
sƂɐʍ рǀɹoʍ əɥʇ oS
kardinal
帖子: 750
注册时间: 2006-03-19 11:39

#6

帖子 kardinal » 2008-07-26 21:20

不好意思 配置文件里的提示符只能用一种
我把另一个单独写在下面了
第二种提示符还有一点小问题 我再看看
kardinal
帖子: 750
注册时间: 2006-03-19 11:39

#7

帖子 kardinal » 2008-07-26 21:38

第二种提示符比较麻烦
我重新弄了下
控制台下使用有点问题,提示符不能正确的换行
在其它地方用,应该没有什么问题了
因为我一般不用这个提示符,所以都有什么问题我也不知道:lol:
要有问题告诉我
头像
sinyadvan
帖子: 724
注册时间: 2008-04-02 15:36
来自: O_O

#8

帖子 sinyadvan » 2008-07-26 21:49

:) 挺好的
上次由 sinyadvan 在 2008-08-23 8:57,总共编辑 1 次。
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

#9

帖子 eexpress » 2008-07-26 21:57

右对齐,似乎都可以吧。如果带设置的话。

其他的shell,都坚持不久的。

比如fish,也会碰到很麻烦的地方。还是bash吧。
● 鸣学
kardinal
帖子: 750
注册时间: 2006-03-19 11:39

#10

帖子 kardinal » 2008-07-26 21:59

sinyadvan 写了::) 挺好的,LZ可以试试fish,我正在用,很不错。
我用的第二个Shell就是Fish
论坛里有一份叫作<Ubuntu教程>的文档,里面专门介绍了Fish。那个文档就是我写的 :lol:

那个时候确实觉得Fish很不错,但是有一些缺点也比较明显,所以后来不用了
比如说:
运行效率低
一些内建命令和Bash不一样
缩略显示路径有时显得不很清晰
提示信息过于详细(没错,刚接触时,这是很大的优点;时间长了这绝对是缺点)
……
kardinal
帖子: 750
注册时间: 2006-03-19 11:39

#11

帖子 kardinal » 2008-07-26 22:02

eexpress 写了:右对齐,似乎都可以吧。如果带设置的话。

其他的shell,都坚持不久的。

比如fish,也会碰到很麻烦的地方。还是bash吧。
如上所说,Fish确实没坚持多久
作人不能这么盲目,为了确信Zsh足够优秀
这次,我特意在使用半年之后才告诉大家 :lol:

用了这么长时间,我没有觉得有一点的厌烦
相反的,有时不得已使用Bash,倒是不胜其烦

另:右对齐似乎只有Zsh可以的吧,它默认配置就有右提示符
而Zsh的介绍里专门提及这一点
如果其它的Shell都可以右对齐,那它没必要拿一个大家都有的功能来炫耀吧
头像
zhuqin_83
帖子: 10606
注册时间: 2006-05-13 4:02
联系:

#12

帖子 zhuqin_83 » 2008-07-26 22:49

加精了
HP Pavilion DV6-2064CA: AMD Turion II Ultra Dual-Core Mobile M640, HD4650, 2GBx2 DDR2-800, Seagate 500GB 7200RPM SATA, BD-ROM
DELL UltraSharp 2209WA
Arch64, Testing repo
头像
hubert_star
论坛版主
帖子: 5373
注册时间: 2007-10-29 22:12
系统: OSX 10.9 + Ub 1304
来自: 江苏南京

#13

帖子 hubert_star » 2008-07-26 23:17

设置为默认shell后,如何更改gnome终端的标题?

在bash里面是自动识别的,但是在zsh下面标题不能自动改变,应该怎样实现?
佛经说,人有八苦: 生、老、病、死、求不得、怨憎、爱别离、五阴盛 故我苦!
圣经说,人有七罪: 饕餮、贪婪、懒惰、淫欲、傲慢、嫉妒和暴怒  故我有罪!

我这篇帖子里面没有任何攻击我们伟大的中华人民共和国政府和任劳任怨的人民公仆(和本论坛高素质的版主)的文字和含义;

特此声明!

有些事,我们明知道是错的,也要去坚持,因为不甘心;有些人,我们明知道是爱的,也要去放弃,因为没结局;有时候,我们明知道没路了,却还在前行,因为习惯了。

欢迎来我的新浪微博@me
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

#14

帖子 eexpress » 2008-07-26 23:28

半年测试啊。这还算认真的哦。
路径别名
这个听着倒是不错。我在bash还专门用一个ccdd脚本作这事。不知道这别名后,还补全等正常不。

建议再说说不爽的地方,给大家参考哦。
● 鸣学
头像
hubert_star
论坛版主
帖子: 5373
注册时间: 2007-10-29 22:12
系统: OSX 10.9 + Ub 1304
来自: 江苏南京

#15

帖子 hubert_star » 2008-07-26 23:33

光顾着看楼主给的配置了,忘记FAQ这个好东西了!
在.zshrc里面加入如下的代码就可以即时更改标题了:

代码: 全选

  chpwd() {
    [[ -t 1 ]] || return
    case $TERM in
      sun-cmd) print -Pn "\e]l%~\e\\"
        ;;
      *xterm*|rxvt|(dt|k|E)term) print -Pn "\e]2;%~\a"
        ;;
    esac
  }

佛经说,人有八苦: 生、老、病、死、求不得、怨憎、爱别离、五阴盛 故我苦!
圣经说,人有七罪: 饕餮、贪婪、懒惰、淫欲、傲慢、嫉妒和暴怒  故我有罪!

我这篇帖子里面没有任何攻击我们伟大的中华人民共和国政府和任劳任怨的人民公仆(和本论坛高素质的版主)的文字和含义;

特此声明!

有些事,我们明知道是错的,也要去坚持,因为不甘心;有些人,我们明知道是爱的,也要去放弃,因为没结局;有时候,我们明知道没路了,却还在前行,因为习惯了。

欢迎来我的新浪微博@me
回复