什么是你最喜欢使用Bash命令行技巧?

我们都知道如何使用<ctrl>-R来反向search历史,但是您是否知道如果设置stty stop ""您可以使用<ctrl>-S来转发search? 另外,你有没有试过运行bind -p来查看列出的所有键盘快捷键? Mac OS X默认有超过455个。

什么是你最喜欢的最隐秘的技巧,键盘快捷方式或使用bash的configurationconfiguration?

快速重命名/移动带有后缀的文件:
cp /home/foo/realllylongname.cpp{,-old}

这扩展到:
cp /home/foo/realllylongname.cpp /home/foo/realllylongname.cpp-old

 cd - 

这是相当于后退button的命令行(将您引导至之前的目录)。

另一个最爱:

 !! 

重复你的最后一个命令。 最有用的forms是:

 sudo !! 

我最喜欢的是使用最后一个命令的'^ string ^ string2',用string2replacestring并执行它

 $ ehco foo bar baz bash: ehco: command not found $ ^ehco^echo foo bar baz 

Bash命令行历史指南

改名

例:

 $ ls this_has_text_to_find_1.txt this_has_text_to_find_2.txt this_has_text_to_find_3.txt this_has_text_to_find_4.txt $ rename 's/text_to_find/been_renamed/' *.txt $ ls this_has_been_renamed_1.txt this_has_been_renamed_2.txt this_has_been_renamed_3.txt this_has_been_renamed_4.txt 

非常有用

我是!$ !^!* expandos的粉丝,从最近提交的命令行返回:最后一个项目,第一个非命令项目和所有非命令项目。 (请注意,shell首先打印出命令):

 $ echo foo bar baz foo bar baz $ echo bang-dollar: !$ bang-hat: !^ bang-star: !* echo bang-dollar: baz bang-hat: foo bang-star: foo bar baz bang-dollar: baz bang-hat: foo bang-star: foo bar baz 

当你说ls filea fileb并且想要编辑它们中的一个: vi !$或者它们两个: vimdiff !*时,这就派上用场了。 它也可以概括为“第n个参数”,如下所示:

 $ echo foo bar baz $ echo !:2 echo bar bar 

最后,通过path名,你可以通过在上面的expandos中添加:h:t来获得部分path:

 $ ls /usr/bin/id /usr/bin/id $ echo Head: !$:h Tail: !$:t echo Head: /usr/bin Tail: id Head: /usr/bin Tail: id 

当运行命令时,有时我会想用前面的参数运行一个命令。 要做到这一点,你可以使用这个捷径:

 $ mkdir /tmp/new $ cd !!:* 

偶尔,代替使用find,如果我需要在一个文件列表上运行一堆命令,我将分出一个单行循环。

 for file in *.wav; do lame "$file" "$(basename "$file" .wav).mp3" ; done; 

在.bash_login(或.bashrc)中configuration命令行历史logging选项是非常有用的。 以下是我在Macbook Pro上使用的一系列设置。

设置下面的命令会让bash在历史logging中清除重复的命令:

 export HISTCONTROL="erasedups:ignoreboth" 

我也支持我的历史规模相当高。 为什么不? 目前的微处理器似乎并没有放慢速度。

 export HISTFILESIZE=500000 export HISTSIZE=100000 

我做的另一件事是忽略我的历史命令。 不需要记住退出命令。

 export HISTIGNORE="&:[ ]*:exit" 

你一定要设置histappend。 否则,bash将在您退出时覆盖您的历史logging。

 shopt -s histappend 

我使用的另一个选项是cmdhist。 这使您可以将多行命令作为一个命令保存到历史logging中。

 shopt -s cmdhist 

最后,在Mac OS X上(如果您不使用vi模式),您将需要将<CTRL> -S重置为滚动停止。 这可以防止bash能够将其解释为向前search。

 stty stop "" 

如何列出当前的子目录?

 ls -d */ 

这是一个简单的伎俩,但是你不知道我需要多less时间来find那个!

ESC

插入最后一个bash命令的最后一个参数。 它比你想象的更方便。

 cp file /to/some/long/path 

光盘ESC

当然,你可以“ diff file1.txt file2.txt ”,但Bash支持进程replace ,它允许你diff file1.txt file2.txt命令的输出。

例如,假设我想确保我的脚本能够提供我期望的输出。 我可以把我的脚本包装在<()中,并把它传递给diff来获得一个快速和脏的unit testing:

 $ cat myscript.sh #!/bin/sh echo -e "one\nthree" $ $ ./myscript.sh one three $ $ cat expected_output.txt one two three $ $ diff <(./myscript.sh) expected_output.txt 1a2 > two $ 

再举一个例子,假设我想检查两台服务器是否安装了相同的RPM列表。 而不是每个服务器sshing,写每个RPM列表来分隔文件,并对这些文件进行diff ,我可以做我的工作站的diff

 $ diff <(ssh server1 'rpm -qa | sort') <(ssh server2 'rpm -qa | sort') 241c240 < kernel-2.6.18-92.1.6.el5 --- > kernel-2.6.18-92.el5 317d315 < libsmi-0.4.5-2.el5 727,728d724 < wireshark-0.99.7-1.el5 < wireshark-gnome-0.99.7-1.el5 $ 

“高级Bash脚本指南”中的更多示例位于http://tldp.org/LDP/abs/html/process-sub.html

我最喜欢的命令是“ls -thor”

它召集神灵的力量以便于阅读的格式列出最近修改过的文件。

更多的新奇,但它很聪明…

使用的十大命令:

 $ history | awk '{print $2}' | awk 'BEGIN {FS="|"}{print $1}' | sort | uniq -c | sort -nr | head 

示例输出:

  242 git 83 rake 43 cd 33 ss 24 ls 15 rsg 11 cap 10 dig 9 ping 3 vi 

^ R反向search。 点击^ R,键入要匹配的前一个命令的片段,然后按^ R直到find所需的命令。 那么我不必记得最近使用的命令,这些命令仍然在我的历史中。 不仅仅是bash,还有:^ E表示行尾,^ A表示行首,^ U和^ K表示分别在光标前后删除。

我经常有vi,ls等的别名,但有时候你想逃避别名。 只需在前面的命令中添加一个反斜杠:

例如:

 $ alias vi=vim $ # To escape the alias for vi: $ \vi # This doesn't open VIM 

很酷,不是吗?

这里有几个configuration调整:

~/.inputrc

 "\C-[[A": history-search-backward "\C-[[B": history-search-forward 

这与^R相同,但使用方向键代替。 这意味着我可以键入(例如) cd /media/然后点击向上箭头去我最后一件事cd /media/ d /media/文件夹。

(我使用Gnometerminal,您可能需要更改其他terminal仿真程序的转义码。)

Bash完成也是非常有用的,但它是一个更微妙的加法。 在~/.bashrc

 if [ -f /etc/bash_completion ]; then . /etc/bash_completion fi 

这将启用每个程序的标签完成(例如,当命令行以evince开头时,试图完成标签只会显示evince可以打开的文件,并且也将制表符完成命令行选项)。

~/.inputrc

 set completion-ignore-case on set show-all-if-ambiguous on set show-all-if-unmodified on 

我用了很多:

:p修饰符打印历史logging结果。 例如

 !!:p 

将打印最后一个命令,以便在再次运行之前检查它是否正确。 只要input!! 执行它。

以类似的方式:

 !?foo?:p 

将search历史logging中包含string“foo”的最新命令并将其打印。

如果你不需要打印,

 !?foo 

做search并马上执行它。

我有一个秘密武器: 炮弹。

智能技巧有一千种,很酷的技巧和高效的食谱,大部分时间都适合在一条线上。

我喜欢的一个(但是因为我使用Python在大多数Unix系统上安装的事实,所以我作弊了一下):

 alias webshare='python -m SimpleHTTPServer' 

现在每次input“webshare”,当前的目录都可以通过端口8000使用。当你想和本地networking上的朋友共享文件,而不使用USB密钥或远程目录时,真的很好。 stream式video和音乐也将起作用。

当然,经典的叉式炸弹是完全没有用的,但仍然很有趣:

 $ :(){ :|:& };: 

不要在生产服务器上尝试…

您可以将watch命令与其他命令结合使用来查找更改。 一个例子就是当我testing我的路由器时,我想获得最新的数字,比如信噪比等。

 watch --interval=10 lynx -dump http://dslrouter/stats.html 
 type -a PROG 

为了findPROG可用的所有地方,通常在〜/ bin中的某处,而不是/ usr / bin / PROG中可能已经预期的地方。

我喜欢用echo构造命令并将它们传递给shell:

 $ find dir -name \*~ | xargs echo rm ... $ find dir -name \*~ | xargs echo rm | ksh -s 

为什么? 因为这让我可以在做之前看看会做什么。 这样,如果我有一个可怕的错误(如删除我的主目录),我可以赶在它发生之前。 显然,这对破坏性或不可撤销的行为来说是最重要的。

在下载大文件时,我经常这样做:

 while ls -la <filename>; do sleep 5; done 

然后只需按Ctrl + C完成(或如果ls返回非零)。 它类似于watch程序,但它使用shell,所以它在没有watch平台上工作。

另一个有用的工具是netcat或nc 。 如果你这样做:

 nc -l -p 9100 > printjob.prn 

然后,您可以在另一台计算机上设置打印机,而使用运行netcat的计算机的IP地址。 打印作业发送时,由运行netcat的计算机接收并转储到printjob.prn

pushdpopd几乎总是派上用场

在树状分层结构中广泛分隔的地方使用多个目录时,一种首选的导航方法是使用acf_func.sh(下面列出)。 一旦定义,你可以做

cd –

用数字菜单查看最近目录的列表

cd -2

去第二个最近的目录。

非常容易使用,非常方便。

代码如下:

 # do ". acd_func.sh" # acd_func 1.0.5, 10-nov-2004 # petar marinov, http:/geocities.com/h2428, this is public domain cd_func () { local x2 the_new_dir adir index local -i cnt if [[ $1 == "--" ]]; then dirs -v return 0 fi the_new_dir=$1 [[ -z $1 ]] && the_new_dir=$HOME if [[ ${the_new_dir:0:1} == '-' ]]; then # # Extract dir N from dirs index=${the_new_dir:1} [[ -z $index ]] && index=1 adir=$(dirs +$index) [[ -z $adir ]] && return 1 the_new_dir=$adir fi # # '~' has to be substituted by ${HOME} [[ ${the_new_dir:0:1} == '~' ]] && the_new_dir="${HOME}${the_new_dir:1}" # # Now change to the new dir and add to the top of the stack pushd "${the_new_dir}" > /dev/null [[ $? -ne 0 ]] && return 1 the_new_dir=$(pwd) # # Trim down everything beyond 11th entry popd -n +11 2>/dev/null 1>/dev/null # # Remove any other occurence of this dir, skipping the top of the stack for ((cnt=1; cnt <= 10; cnt++)); do x2=$(dirs +${cnt} 2>/dev/null) [[ $? -ne 0 ]] && return 0 [[ ${x2:0:1} == '~' ]] && x2="${HOME}${x2:1}" if [[ "${x2}" == "${the_new_dir}" ]]; then popd -n +$cnt 2>/dev/null 1>/dev/null cnt=cnt-1 fi done return 0 } alias cd=cd_func if [[ $BASH_VERSION > "2.05a" ]]; then # ctrl+w shows the menu bind -x "\"\Cw\":cd_func -- ;" fi 

在击中可怕的input之前展开复杂的行

  • Alt + Ctrl + eshell-expand-line (可能需要在键盘上使用EscCtrl + e
  • Ctrl + _撤消
  • Ctrl + x*glob-expand-word

$ echo !$ !-2^ * Alt + Ctrl + e
$ echo aword someotherword * Ctrl + _
$ echo !$ !-2^ * Ctrl + x*
$ echo !$ !-2^ LOG Makefile bar.c foo.h

&C。

我一直偏袒:

 ctrl-E # move cursor to end of line ctrl-A # move cursor to beginning of line 

我也使用shopt -s cdable_vars ,那么你可以创buildbashvariables到公共目录。 所以,对于我公司的源代码树,我创build了一堆variables,如:

 export Dcentmain="/var/localdata/p4ws/centaur/main/apps/core" 

那么我可以通过cd Dcentmain转到那个目录。

pbcopy

这复制到Mac系统剪贴板。 你可以pipe命令给它…试试:

pwd | pbcopy

 $ touch {1,2}.txt $ ls [12].txt 1.txt 2.txt $ rm !:1 rm [12].txt $ history | tail -10 ... 10007 touch {1,2}.txt ... $ !10007 touch {1,2}.txt $ for f in *.txt; do mv $f ${f/txt/doc}; done 

在命令行使用“set -o vi”,或者在.bashrc中使用“set -o vi”,会使您在命令行上进入vi编辑模式。 你开始在'插入'模式,所以你可以正常键入和退格,但是如果你犯了一个'大'的错误,你可以按esc键,然后使用'b'和'f'来回移动。 改变一个词。 在你提出了一个你想改变的历史命令后特别有用。

类似于上面的许多,我目前最喜欢的是按键[alt]。 (Alt和“。”键在一起),这是相同的$! (插入上一个命令的最后一个参数),除了它是直接的,对我来说更容易input。 (只是不能在脚本中使用)

例如:

 mkdir -p /tmp/test/blah/oops/something cd [alt]. 

使用&&命令将多个命令串起来:

 ./run.sh && tail -f log.txt 

要么

 kill -9 1111 && ./start.sh