什么是你最喜欢使用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
。
pushd
和popd
几乎总是派上用场
在树状分层结构中广泛分隔的地方使用多个目录时,一种首选的导航方法是使用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 + e – shell-expand-line (可能需要在键盘上使用Esc , Ctrl + 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