您已经对外壳配置文件进行了哪些自定义以提高生产率?


25

我知道有些人有一些启动脚本,有些人则对提示进行个性化设置。一名开发人员将短别名用于他经常访问的长途路径和他经常运行的命令。

您在UNIX概要文件上进行了哪些有效的自定义操作,以提高生产率和易用性?


应该是CW,不能客观回答。
akira

我同意。但是,CW没有选择。:-(

@akira @Michael我经常遇到这种情况。如果主持人可以编辑/交叉发布/重定向问题,那就太好了。因为您留下的评论对用户实现其真正想要的功能没有多大帮助。没有犯罪,只是一个建议。希望你能理解。

如果要制作问题社区Wiki,请标记它以引起主持人注意。请参阅社区Wiki常见问题解答
吉尔(Gilles)“所以,别再邪恶了”,

Answers:


11

.vimrc

通过输入w!!以下内容以root用户权限保存文件:

cmap w!! w !sudo tee % > /dev/null


.bashrc

greping 时,请勿打扰设备或二进制文件:

alias grep='grep --color=auto --binary-files=without-match --devices=skip'


通过以下方式在网络上共享代码(例如pastebin,但更简单) cat 1337.sh | webshare

alias webshare='curl -F "sprunge=<-" http://sprunge.us | xclip'

它会在您的剪贴板中返回一个简短的网址;您可以将其附加?whatever-lang到返回的URL上,以突出显示其语法并为行编号。


.inputrc

在使用readline库的所有内容中使用vi模式(许多程序):

set editing-mode vi
set keymap vi

我不知道的好提示。

7

在一个命令中创建目录和cd

大多数时候mkdir,我的下一个命令是cd <that dir>

这样可以节省一些输入:

# make a directory and cd to it
mcd()
{
    test -d "$1" || mkdir "$1" && cd "$1"
}

例如:

/home/mikel$ mcd somedir
/home/mikel/somedir$ 

我发现有用的另一件事是制作一次性目录的简便方法。例如,如果我正在编译程序,或者即使我正在尝试在此站点上重现问题。有时我可能会忘记清理目录。

# make a temporary directory and cd to it
mtd()
{
    local dir
    dir=$(mktemp -d)
    if test -n "$dir"
    then
        if test -d "$dir"
        then
            echo "$dir"
            cd "$dir"
        else
            echo "mktemp directory $dir does not exist"
        fi
    else
        echo "mktemp didn't work"
    fi
}

显示它的工作原理:

/home/mikel$ mtd
/tmp/tmp.wsnZjJ2KN6
/tmp/tmp.wsnZjJ2KN6$ 

我依靠的/tmp是重新启动后清理系统,但是可以增强此功能,例如,使其退出外壳后删除temp dir。


我喜欢mcd选项。很好,谢谢。

+1我已经使用mcd了多年的版本,mtd不久将添加一些内容。
maaartinus 2011年

我定义了我的mtd() { mcd $TMP/`date +%y%m%d-%H%M%S-%N`; }。它可能缺乏便携性,但是对我来说已经足够了。
maaartinus 2011年

4

我想让bash提示符显示前一个命令的退出代码(如果它不为零)。我也喜欢我的外壳在使用时为我加油,所以我增加了一些傻气:

smiley() {
    RC=$?
    [[ ${RC} == 0 ]] && echo ':)' || echo ":( ${RC}"
}

export PS1="\$(smiley) \h [\A] [\W] \$ "

因此,当我运行命令时,会得到一些不错的视觉反馈:

:) mycomputer [23:03] [~] $ sh -c 'exit 0'
:) mycomputer [23:03] [~] $ sh -c 'exit 11'
:( 11 mycomputer [23:03] [~] $ 

编辑:这是我放在〜/ .bashrc中的东西


挺有意思。但是,我有一个疑问。代码应该放在哪里?

.bashrc大概在。
Mikel

是的,那是在我的〜/ .bashrc中
jsbillings,2011年

将尝试..

4

最多N

在目录树中向上跳转N个目录

不用打字

cd ../../../..

你只要输入

up 4

和一个

cd -    

会带你回来

将该函数放入您的.bashrc中以使用它。

# (c) 2007 stefan w. GPLv3          
function up {
ups=""
for i in $(seq 1 $1)
do
        ups=$ups"../"
done
cd $ups
}

哇..这是一个不错的主意..

2

.zshrc

alias l='ls -CF'
alias ll='ls -ClhF'
alias la='ls -CaF'
alias lla='ls -CalhF'
alias l.='ls -CAF --ignore=\*'
alias ll.='ls -CAlhF --ignore=\*'
alias t='tree -C'

PS1=$'%{\e[0;33m%}%m %{\e[32;1m%}%~ %{\e[0;31m%}%#%{\e[m%} '

bindkey '^[[3~' delete-char

export GREP_OPTIONS="--color"

.xmodmaprc

clear lock
keycode 9 = Caps_Lock ISO_Next_Group Caps_Lock ISO_Next_Group
keycode 66 = Escape NoSymbol Escape
add lock = Caps_Lock

(交换Escape键和Caps Lock键)。


+1以重新映射键,我的Caps Lock映射为Return,无论如何仍需要大写锁定?
WAG

1
我是Vim用户。Vim用户通常会将Escape映射到Caps Lock。Emacs用户倾向于将Control映射到Caps Lock。
polemon 2011年

1

因为我经常使用终端,所以我搞砸了bashrc(这使我可以快速学习并学习一些有趣的东西以及有趣的工具)。我通常在bashrc中定义许多功能。例子:

提取档案:

extract () {
libextract () {
if [ -f "$1" ] ; then
  case "$1" in
    *.tar.bz2) tar xjf "$1" ;;
    *.tar.gz)  tar xzf "$1" ;;
    *.bz2) bunzip2 "$1" ;;
    *.rar) rar x "$1" ;;
    *.gz) gunzip "$1" ;;
    *.tar) tar xf "$1" ;;
    *.tbz2) tar xjf "$1" ;;
    *.tgz) tar xzf "$1" ;;
    *.zip) unzip "$1" ;;
    *.Z) uncompress "$1" ;;
    *.7z) 7z x "$1" ;;
    *) echo "$1 ne moze biti raspakovan!" ;;
  esac
else
  echo "$1 nije validan fajl"
fi
}
 echo "Unesite putanju do direktorijuma u kome se nalaze arhive: " && read dir && dirprovera && cd $dir
  for f in *
    do
      mkdir ./$f-raspakovano && cd ./$f-raspakovano
      libextract ./../$f
      cd ./../
    done
  tipka
}

重命名文件和文件夹:

frename () {
if [ $# -gt 0 ]
then
 dir="$(echo $1)"
  dirprovera
  cd $dir
  for f in *
    do
      mv "$f" "`echo "$f" | tr -s " " "_" | tr "A-Z" "a-z"`" 2>/dev/null &
    done
  tipka
else
 echo "Upotreba: frename [direktorijum]" >&2
fi
}

像这样将大文件分割成几个小文件:

fsplit () {
if [ $# -gt 1 ]
then
 file="$(echo $1)"
 SIZE="$(echo $2)"
 PREFIX="$(echo $3)"
 if [ -z "$PREFIX" ]; then PREFIX="fsplit"; fi
  fileprovera
  split -d -a 3 -b $SIZE $file "$PREFIX-part-" || echo "Doslo je do greske!"
  tipka
else
 echo "Upotreba: fsplit [fajl] [velicina] [prefix]
Za velicinu se koriste m (MB), g (GB) ili k (KB) (15m, 650kb, 4.7g...)

Prefiks moze sadrzati brojeve, slova, i crtice (primer: moj_pre-fiks)
Ukoliko ne unesete prefiks isti ce biti dodeljen automatski u sledecem formatu:
  fsplit-part-XXX
gde XXX predstavlja broj dela fajla (001, 005, 189...)" >&2
fi
}

我还编辑了很多别名,因为我发现在某些情况下(例如在ls,grep和small命令中)使用带有默认参数的命令要容易得多,然后每次键入所有这些都容易得多。


1

(社区Wiki,因此每个技巧都属于一个单独的答案。)

安全登出

Ctrl+ D是退出Shell的最简单方法,但是如果仍然有作业在运行,无论如何它都会很高兴地退出Shell。默认情况下,这意味着您从该Shell内部运行的所有程序都将被杀死。

某些shell仅在按Ctrl+ D两次后才让您注销,但是意外地这样做仍然太容易了。

因此,请将其添加到.bashrc.zshrc或您喜欢的任何配置文件中。

alias x='_exit'

# prevent running "exit" if the user is still running jobs in the background
# the user is expected to close the jobs or disown them
_exit()
{
    case $- in *m*)
        # this way works in bash and zsh
        jobs | wc -l | grep -q '^ *0 *$'
        if test $? -eq 0
        then
            command exit "$@"
        else
            jobs
        fi
        ;;
    *)
        command exit "$@"
        ;;
    esac
}

1

(社区Wiki,因此每个技巧都属于一个单独的答案。)

搜索历史记录以查找运行命令的所有方式

您可能已经知道Ctrl+ R,但是恕我直言,这种方法更加流畅。

设置Alt+ P以在历史记录中搜索以您已经键入的内容开头的命令。

例如ls Alt+ PAlt+ PAlt+ P 将通过所有ls命令向后搜索。

您需要将其放入/etc/inputrc.inputrcbash

$if mode=emacs
"\ep": history-search-backward
"\en": history-search-forward
$endif

这对于您.zshrc来说zsh

bindkey -M emacs '^[p' history-beginning-search-backward
bindkey -M emacs '^[n' history-beginning-search-forward

您甚至可以更进一步,使“向上”箭头执行此操作。


1

简单的计算器

您可以使用$(( ... ))expr ...进行非常基本的计算,但是可以进行整数除法,例如

$ expr 3 / 2
1

$ expr 1.5 \* 2
expr: non-integer argument

更好的方法是使用bc

# do some floating point arithmetic
calc()
{
    echo "scale=3; $*" | bc
}

然后:

$ calc 3 / 2
1.500
$ calc 1.5 \* 2
3.0

1
该文件中alias py='PYTHONSTARTUP=~/.pythonstartup python'包含我的计算器from math import *;。整数除法问题仍未解决,但是它对于更复杂的操作更有用。
maaartinus 2011年

1

更好的制表符完成

我认为还没有人提到自定义Tab完成。

这就是我所拥有的。

它做的两个主要事情是:

  • 每个命令将根据命令的期望完成制表符,
    例如cd <Tab>仅建议目录
  • 忽略情况,
    例如d<Tab>仍将完成DesktopDownloads

对于bash:

# custom tab completions
if type complete >/dev/null 2>&1
then
    if complete -o >/dev/null 2>&1
    then
        COMPDEF="-o complete"
    else
        COMPDEF="-o default"
    fi
    complete -a alias unalias
    complete -d cd pushd popd pd po
    complete $COMPDEF -g chgrp 2>/dev/null
    complete $COMPDEF -u chown
    complete -j fg
    complete -j kill
    complete $COMPDEF -c command
    complete $COMPDEF -c exec
    complete $COMPDEF -c man
    complete -e printenv
    complete -G "*.java" javac
    complete -F complete_runner -o nospace -o default nohup 2>/dev/null
    complete -F complete_runner -o nospace -o default sudo 2>/dev/null
    complete -F complete_services service
    # completion function for commands such as sudo that take a
    # command as the first argument but should complete the second
    # argument as if it was the first
    complete_runner()
    {
        # completing the command name
        # $1 = sudo
        # $3 = sudo
        # $2 = partial command (or complete command but no space was typed)
        if test "$1" = "$3"
        then
            set -- `compgen -c "$2"`
        # completing other arguments
        else
            # $1 = sudo
            # $3 = command after sudo (i.e. second word)
            # $2 = arguments to command
            # use the custom completion as printed by complete -p,
            # fall back to filename/bashdefault
            local comps
            comps=`complete -p "$3" 2>/dev/null`
            # "complete -o default -c man" => "-o default -c"
            # "" => "-o bashdefault -f"
            comps=${comps#complete }
            comps=${comps% *}
            comps=${comps:--o bashdefault -f}
            set -- `compgen $comps "$2"`
        fi
        COMPREPLY=("$@")
    }

    # completion function for Red Hat service command
    complete_services()
    {
        OIFS="$IFS"
        IFS='
        '
        local i=0
        for file in $(find /etc/init.d/ -type f -name "$2*" -perm -u+rx)
        do
            file=${file##*/}
            COMPREPLY[$i]=$file
            i=$(($i + 1))
        done
        IFS="$OIFS"
    }
fi

对于zsh:

# set command completions
compctl -a {,un}alias
compctl -b bindkey
compctl -c command
compctl -/ {c,push,pop}d
compctl -E {print,set,unset}env
#compctl -c exec
compctl -f -x "c[-1,exec]" -c -- exec
compctl -j fg
# no -g according to zshcompctl
#compctl -g {ch}grp
compctl -j kill
compctl -c man
compctl -c nohup
compctl -u {ch}own
compctl -o {set,unset}opt
compctl -f -x "c[-1,sudo]" -c -- sudo
compctl -c {whence,where,which}
compctl -M '' 'm:{a-zA-Z}={A-Za-z}'

# make file name completion case-insensitive
zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}'

1

安全压缩

压缩程序默认情况下会删除原始文件。我不喜欢

alias gzip='gzip --keep'
alias bzip2='bzip2 --keep'
alias xz='xz --keep'
alias lzma='lzma --keep'

多行提示

tag() {
    TAG="${TAG} [$1]" exec zsh
}

reset_tags() {
    TAG='' exec zsh
}

color='green'
if [ "${USER}" = 'root' ]; then
    color='red'
fi

export PS1="${TAG} %B%F{yellow} *** %F{blue}%~\

%F{yellow}%(1j.[%j] .)%F{red}%(?..(%?%) )%F{${color}}%n@%m %F{blue}%# %f%b"
export RPS1='%B%F{blue}%D{%Y-%m-%d} %F{green}%D{%H:%M:%S}'
export PS2='%B%F{red}%n@%m%k %B%F{blue}%_> %b%f%k'
unset color
  • 在单独的行中显示当前目录。在80列终端上处理深层目录树时很有用。
  • 如果使用图形环境,那么在角落里摆个时钟是一件好事。此提示显示时间。不幸的是,您必须按Enter进行更新。
  • 您可以显示带有环境变量的“标签”。例:

    tag 'DONT SHTUDOWN!!'
    reset_tags
    
  • 该代码至少部分基于this

历史记录设置

dont_log() {
    HISTFILE="/dev/null" TAG="${TAG} %B%F{red}[LOGGING DISABLED]" zsh
}

if [ "${HISTFILE}" != '/dev/null' ]; then
    # history
    export HISTFILE="${HOME}/.zsh/history"
    export HISTSIZE="4096"
    export SAVEHIST="4096"

    # Don't overwrite, append!
    setopt APPEND_HISTORY

    # Write after each command
    # setopt INC_APPEND_HISTORY

    # Killer: share history between multiple shells
    setopt SHARE_HISTORY

    # If I type cd and then cd again, only save the last one
    setopt HIST_IGNORE_DUPS

    # Even if there are commands inbetween commands that are the same, still only save the last one
    setopt HIST_IGNORE_ALL_DUPS

    # Pretty    Obvious.  Right?
    setopt HIST_REDUCE_BLANKS

    # If a line starts with a space, don't save it.
    setopt HIST_IGNORE_SPACE
    setopt HIST_NO_STORE

    # When using a hist thing, make a newline show the change before executing it.
    setopt HIST_VERIFY

    # Save the time and how long a command ran
    setopt EXTENDED_HISTORY

    setopt HIST_SAVE_NO_DUPS
    setopt HIST_EXPIRE_DUPS_FIRST
    setopt HIST_FIND_NO_DUPS
fi
  • 这里被无耻地偷
  • 我添加了对显式禁用日志记录的支持。如果您正在处理需要密码作为CLI参数的程序,则很有用。

0
  • bashrc:我是zsh用户,所以在bashrc中有几行启动zsh(如果系统上可用)。
  • zshrc:而不是从grml之类的文件中复制我的zshrc(尽管zshrc非常好,所以如果您不想自己动手,可能是最好的方法之一),我编写了自己的zshrc。
    • 我有一个自定义的提示。除其他事项外,如果不等于0,它还显示最后一条命令的返回码。
    • 我有一些别名。因为我在许多服务器上都有帐户,所以有时我必须检查系统上可用的命令版本,并相应地设置别名。
    • 我设置了PATH变量。
    • 我设置了其他一些环境变量(例如$ EDITOR)
  • vimrc:我是vim用户,所以我有一个自定义的和自定义的配色方案。
  • screenrc:我使用GNU屏幕来避免不必打开多个终端并在不登录时保留历史记录,因此我有自己的screenrc。

0

如果您可以打开自动完成和文件名拼写更正!这可能是两件事可以为您节省最多的时间。然后,学习使用它们-Bash和Zsh具有制表符补全功能。Ksh的转义反斜杠效率很低,因此我建议不要使用Ksh。

我用的是Zsh,但是这样的别名几乎可以在除Csh之外的所有shell中使用:

alias l='ls -FC --color=tty'
alias ls='ls -FC --color=tty'
alias h=history
alias m=more
alias vi=vim
alias cx='chmod +x'

似乎应该在其中加上“ ps”的别名,但是我发现自己以多种方式使用“ ps”,但到目前为止我还没有发现任何东西。

在Zsh中,设置您的RPROMPT(不是拼写错误!)变量:

RPROMPT='%d'

整个目录显示在命令行的右侧,可以进行剪切粘贴。以后再说。

您应该使用正确编译的现代Vim,因为它可以将多个vim窗口放入一个文件和多个缓冲区中。您的.vimrc可能包含以下内容:

set mouse=c
set ml
set mls=5
set nowrap
set nobackup
set nonu
set showmatch
set tabstop=4
set shiftwidth=4
set showmode
set showcmd
set ruler
set notextauto
set laststatus=2
set mps=(:),{:},[:],<:>
set modelines=0

其中很多是个人喜好,但我确实相信8空格制表符会使代码的可读性降低,并且有大量研究对此进行了证明。

同样,“ mouse = c”很重要。您不应该使用鼠标在文件内移动。将手从键盘上移开,触摸鼠标,然后将它们向后移,这很慢。使用“ hjkl”光标移动以及其他键盘分页和光标移动键。

如果您使用的是X11,则应对Xterm配置进行一些操作。这来自我的.Xresources文件:

XTerm*VT100.scrollBar: true
XTerm*VT100.saveLines: 1000
XTerm*VT100.cutNewLine: false 
XTerm*VT100.cutToBeginningOfLine: false
XTerm*VT100.charClass: 33:48,35:48,37:48,42:48,45-47:48,64:48,95:48,126:48
XTerm*VT100*translations: #override \n\
    <Key>F2: insert-selection(PRIMARY,CUT_BUFFER0)

默认情况下,给Xterm一个滚动条,在缓冲区中保存1000行文本,这很标准。

charClass指令使“单词”包含诸如“。”,“ /”和“ *”之类的内容。双击以“ /”分隔的文件名的任何部分,就可以得到整个内容,少了“:”字符。

cutToBeginningOfLine与上面的Zsh RPROMPT一起使用。三次单击出现在命令行RHS上的当前工作目录的路径,然后仅选择路径:复制停止在单词的开头。习惯了之后就会非常高效。

上面的X资源还使成为粘贴键。这样,复制(可能使用鼠标)后,您可以粘贴而无需将手移回鼠标单击。


FWIW,该文件名的完成Esc``EscEsc``=ksh,并Tab在工作ksh93。以防万一有人卡住或喜欢它。
Mikel

0

添加最后一个命令的非零返回值是一个好主意。我认为原始海报专门询问了.profile / .cshrc / .bashrc。值得一提的是其他通常自定义的RC文件的列表,但是对于这个问题,我只会坚持使用shell自定义。

最近,我还在提示符下添加了一个标志,该标志在shell在屏幕下运行时显示。它使用solaris的“ ptree”命令搜索祖先进程,但是您可以在Linux上使用“ pstree”命令执行相同的操作。

SCREEN=""
if [ -f /usr/bin/ptree ]; then
   if ptree $$ | grep -v grep | grep -w screen > /dev/null 2>&1; then
       SCREEN="SCREEN "
   fi
fi

我花了几分钟的时间弄清楚如何嵌入最后一条命令的返回代码,因此我将其张贴在这里。

PROMPT_COMMAND='if [ "$?" = 0 ]; \
        then RC=""; \
        else RC="RV=$? "; fi; PS1="% ${SCREEN}\h $RC\w\n% "'

我敢肯定,可以做得更漂亮。:-)

未来的技巧,请注意阅读$?在使用“ if [”之后。如果左括号是内置括号,它将不会覆盖$?的值。但是,如果您使用[不是内置的shell,那么它将重置$?的值?经过测试。分配$更安全?立即放入一个临时变量,然后测试该变量。


您的答案可能应该是评论...像这样!
VxJasonxV

0

显示最近更改的文件

通常,我想查看最新的文件。例如,我可能在logs目录中,并想查看哪个文件是最新的,因为这是查看为什么某些文件不起作用的第一个地方。

ls -lt | head 输入起来很麻烦,所以这里有一个替代方法:

# show the most recently changed file
latest()
{
    if test $# -ne 0
    then
        /bin/ls -t -1 -d "$@" | head -n 1
    else
        /bin/ls -t -1 -d * | head -n 1
    fi
}

它还需要一个通配符或文件列表,例如

$ latest mail* syslog*
syslog

如果所有日志文件的名称都带有时间戳,这将特别方便。您可以找到该程序的最新日志,而不必担心时间戳的格式。

$ touch -d 'Feb 1' mylog.20110201
$ touch -d 'Feb 2' mylog.20110202
$ touch -d 'Feb 3' mylog.20110203
$ latest mylog*
mylog.20110203

这是扩展版本,支持-<number>打印<number>行而不是一行的选项。

# show the most recently changed file
latest()
{
    local count=1               # how many files to print
    local promptlines=5         # how many lines to leave for the prompt
                                # when printing a screenful with -s
    local usage="Usage: latest [-n <number>] [-s] [--] [pattern]"
    while test $# -gt 0
    do
        case $1 in
        # -- = stop processing options
        --)
            shift
            break
            ;;
        # -n <number> = <number> files
        -n)
            if test -n "$2"
            then
                count=$2
                shift 2
            else
                echo "$usage" 1>&2
                return 1
            fi
            ;;
        # -s = one screenful
        -s)
            count=$((LINES - promptlines))
            shift
            ;;
        # -<number> = <number> files
        -[0-9]*)
            count=${1#-}
            shift
            ;;
        # anything else starting with a minus is a usage error
        -*)
            echo "$usage" 1>&2
            return 1
            ;;
        *)
            break
            ;;
        esac
    done

    if test $# -ne 0
    then
        /bin/ls -t -1 -d "$@" | head -n $count
    else
        /bin/ls -t -1 -d * | head -n $count
    fi
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.