我们都知道如何使用
反向搜索历史记录,但是
如果你设置了,你知道你可以使用转发搜索stty stop ""
吗?另外,您是否尝试过运行bind -p来查看列出的所有键盘快捷键?默认情况下,Mac OS X上有超过455个.
什么是你最喜欢的晦涩难懂的技巧,键盘快捷键或使用bash的shopt配置?
快速重命名/移动带有后缀的文件:
cp /home/foo/realllylongname.cpp{,-old}
这扩展到:
cp /home/foo/realllylongname.cpp /home/foo/realllylongname.cpp-old
cd -
它是后退按钮的命令行等效项(将您带到您以前的目录).
另一个喜欢:
!!
重复你的最后一个命令.最有用的形式:
sudo !!
我最喜欢的是'^ string ^ string2',它接受最后一个命令,用string2替换字符串并执行它
$ 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
最后,使用路径名,您可以通过附加:h
以及:t
上述任何扩展来获取路径的某些部分:
$ 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)中配置命令行历史记录选项非常有用.以下是我在Macbook Pro上使用的一系列设置.
设置以下内容使bash擦除历史记录中的重复命令:
export HISTCONTROL="erasedups:ignoreboth"
我也把我的历史规模提高了很多.为什么不?它似乎并没有减缓今天微处理器的速度.
export HISTFILESIZE=500000 export HISTSIZE=100000
我做的另一件事是忽略我历史上的一些命令.无需记住退出命令.
export HISTIGNORE="&:[ ]*:exit"
你肯定想设置他的.否则,bash会在您退出时覆盖您的历史记录.
shopt -s histappend
我使用的另一个选项是cmdhist.这使您可以将多行命令作为一个命令保存到历史记录中.
shopt -s cmdhist
最后,在Mac OS X上(如果你没有使用vi模式),你需要将
stty stop ""
如何仅列出当前子目录中的子目录?
ls -d */
这是一个简单的技巧,但你不知道我需要多少时间来找到那个!
ESC.
插入上一个bash命令中的最后一个参数.它比你想象的更方便.
cp file /to/some/long/path
光盘 ESC.
当然,你可以" diff file1.txt file2.txt
",但Bash支持进程替换,它允许你diff
输出命令.
例如,假设我想确保我的脚本给出了我期望的输出.我可以将我的脚本包装在<()中并将其输入diff
以获得快速和脏的单元测试:
$ 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 $
http://tldp.org/LDP/abs/html/process-sub.html上的Advanced Bash-Scripting Guide中有更多示例.
我最喜欢的命令是"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反向搜索.按^ R,键入要匹配的上一个命令的片段,然后按^ R直到找到所需的那个.然后我不必记住最近使用的命令仍然在我的历史记录中.不仅仅是bash,而且:^ E表示行尾,^ A表示行的开头,^ U和^ K分别表示在光标前后删除.
我经常为vi,ls等设置别名,但有时你想逃避别名.只需在前面的命令中添加反斜杠:
例如:
$ alias vi=vim $ # To escape the alias for vi: $ \vi # This doesn't open VIM
很酷,不是吗?
这是一些配置调整:
~/.inputrc
:
"\C-[[A": history-search-backward "\C-[[B": history-search-forward
这与^R
使用箭头键相同但工作方式相同.这意味着我可以键入(例如)cd /media/
然后按向上箭头转到我cd
要在/media/
文件夹中的最后一件事.
(我使用Gnome 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
用于打印历史结果的修饰符.例如
!!:p
将打印最后一个命令,以便在再次运行之前检查它是否正确.只需输入!!
执行即可.
与此相类似:
!?foo?:p
将在您的历史记录中搜索包含字符串'foo'的最新命令并打印它.
如果您不需要打印,
!?foo
搜索并立即执行.
我有一个秘密武器:shell-fu.
有大量智能提示,很酷的技巧和高效的食谱,大多数时间都适合一条线.
我喜欢的一个(但是我因为我现在在大多数Unix系统上安装了Python这一事实而作弊):
alias webshare='python -m SimpleHTTPServer'
现在每次输入"webshare"时,当前目录都可以通过端口8000获得.当你想在没有usb密钥或远程目录的本地网络上与朋友共享文件时,真的很好.流媒体视频和音乐也会起作用.
当然,经典的叉炸弹完全没用但仍然很有趣:
$ :(){ :|:& };:
不要在生产服务器中尝试...
您可以将watch命令与另一个命令结合使用以查找更改.这方面的一个例子就是当我测试我的路由器时,我希望获得有关信噪比等信息的最新数据.
watch --interval=10 lynx -dump http://dslrouter/stats.html
我喜欢使用echo构造命令并将它们传递给shell:
$ find dir -name \*~ | xargs echo rm ... $ find dir -name \*~ | xargs echo rm | ksh -s
为什么?因为它允许我在我做之前看看将要做什么.这样,如果我有一个可怕的错误(比如删除我的主目录),我可以在它发生之前捕获它.显然,这对于破坏性或不可撤销的行为最为重要.
type -a PROG
为了找到PROG可用的所有地方,通常在〜/ bin中的某个地方而不是/ usr/bin/PROG中可能已经预期的地方.
下载大文件时,我经常这样做:
while ls -la; do sleep 5; done
然后在我完成时(或者如果ls
返回非零)只需要ctrl + c .它与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 "\"\C-w\":cd_func -- ;" fi
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
,然后你可以创建bash变量到公共目录.所以,对于我公司的源代码树,我创建了一堆变量,如:
export Dcentmain="/var/localdata/p4ws/centaur/main/apps/core"
然后我可以通过更改到该目录cd Dcentmain
.
pbcopy
这将复制到Mac系统剪贴板.你可以管道命令...尝试:
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中,使您在命令行上进入vi编辑模式.你可以在"插入"模式下开始,这样你就可以正常输入和退格,但是如果你犯了一个"大"的错误,你可以点击esc键,然后使用'b'和'f'像在vi中一样移动.cw改变一个词.在您启动了要更改的历史命令之后特别有用.
使用&&命令将多个命令串在一起:
./run.sh && tail -f log.txt
要么
kill -9 1111 && ./start.sh
与上面的许多类似,我目前最喜欢的是击键[alt].(Alt和"."键在一起)这与$相同!(插入上一个命令的最后一个参数),除了它是立即的,并且我更容易键入.(不能在脚本中使用)
例如:
mkdir -p /tmp/test/blah/oops/something cd [alt].
重复的文件查找器
这将从当前目录递归地运行校验和,并返回所有相同校验和结果的文件名:
find ./ -type f -print0 | xargs -0 -n1 md5sum | sort -k 1,32 | uniq -w 32 -d --all-repeated=separate | sed -e 's/^[0-9a-f]*\ *//;'
当然,你可以改变路径.
可能将其放入函数或别名中,并将目标路径作为参数传递.
!
<命令的前几个字符>将执行匹配的最后一个命令.
例:
!b
将运行"构建任何-O -p -t -i -on"
!.
将运行./a.out
它适用于长而重复的命令,如编译,构建,执行等.它在编码和测试时节省了太多时间.
我有很多目录,我想快速访问,CDPATH
变量是解决方案,极大地加快了我的工作流程:
export CDPATH=.:/home/gadolin/sth:/home/gadolin/dir1/importantDir
现在,cd
我可以跳转到任何子目录/home/gadolin/sth
或/home/gadolin/dir1/importantDir
不提供完整路径.而且
在这里工作,就像我会在那里!所以,如果有目录/home/gadolin/sth/1
/home/gadolin/sth/2
,我会cd 1
在任何地方输入,我就在那里.