我们都知道如何使用<ctrl>-R
反向搜索历史记录,但是<ctrl>-S
如果设置了,您是否知道可以使用正向搜索stty stop ""
?另外,您是否曾经尝试运行bind -p来查看列出的所有键盘快捷键?默认情况下,Mac OS X上有超过455个。
使用bash,您最喜欢的晦涩trick俩,键盘快捷键或购物配置是什么?
我们都知道如何使用<ctrl>-R
反向搜索历史记录,但是<ctrl>-S
如果设置了,您是否知道可以使用正向搜索stty stop ""
?另外,您是否曾经尝试运行bind -p来查看列出的所有键盘快捷键?默认情况下,Mac OS X上有超过455个。
使用bash,您最喜欢的晦涩trick俩,键盘快捷键或购物配置是什么?
Answers:
快速重命名/移动带后缀的文件:
cp /home/foo/realllylongname.cpp{,-old}
扩展为:
cp /home/foo/realllylongname.cpp /home/foo/realllylongname.cpp-old
另一个最爱:
!!
重复上一个命令。最有用的形式:
sudo !!
mkdir testdir; cd !$
..运行cd [last word of previous line]
(在示例中cd testdir
)
我最喜欢的是'^ string ^ string2',它接受最后一条命令,用string2替换string并执行
$ ehco foo bar baz
bash: ehco: command not found
$ ^ehco^echo
foo bar baz
!!:gs/ehco/echo/
!!:gs/ehco/echo/
执行全局搜索并替换最后一条命令(!!
在stackoverflow.com/questions/68372/…中授予)。这不等于^ehco^echo
仅仅替换一个“ ehco”实例,而是一个更准确的响应!!:s/ehco/scho
。
改名
例:
$ 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
th参数”,如下所示:
$ echo foo bar baz
$ echo !:2
echo bar
bar
最后,路径名,您可以在路径的部分通过追加获得:h
与:t
上述任何expandos将的:
$ 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"
您肯定要设置histappend。否则,bash会在您退出时覆盖您的历史记录。
shopt -s histappend
我使用的另一个选项是cmdhist。这使您可以将多行命令作为一个命令保存到历史记录中。
shopt -s cmdhist
最后,在Mac OS X上(如果您未使用vi模式),您将要重置<CTRL> -S为滚动停止。这会阻止bash将其解释为正向搜索。
stty stop ""
如何只列出当前目录中的子目录?
ls -d */
这是一个简单的技巧,但是您不知道我需要多少时间才能找到那个!
alias lsd='ls -F | grep --color /'
,它会列出相同的内容,但是方式更la脚。但是,为了便于解析,它会在每行列出一个目录。我已修改您的命令以执行相同的操作:ls -d1 */
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列表。无需在每个服务器上都挂接,将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的《高级Bash脚本指南》中有更多示例。
我最喜欢的命令是“ ls -thor”
它召唤众神以一种方便阅读的格式列出最近修改的文件的能力。
ls -bart -simpson -ruls
。S,ICNR
ls -lort
丹麦语“粪便”一词。省略任何团体,而不会发怒:)
更多新颖,但这很聪明...
使用的前10个命令:
$ 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
history | awk 'BEGIN {FS="[ \t]+|\\|"} {print $3}' | sort | uniq -c | sort -nr | head
^ 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
不错,不是吗?
command
-请SHELL BUILTIN COMMANDS
参阅Bash手册。
这是几个配置调整:
~/.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
补全将仅显示可以打开的文件,并且还将显示制表符补全的命令行选项)。
也可以在~/.inputrc
以下方面很好地工作:
set completion-ignore-case on
set show-all-if-ambiguous on
set show-all-if-unmodified on
我经常使用以下内容:
:p
用于显示历史记录结果的修饰符。例如
!!:p
将打印最后一个命令,以便您可以在再次运行之前检查它是否正确。只需输入!!
执行它。
与此相类似:
!?foo?:p
将在您的历史记录中搜索包含字符串'foo'的最新命令并进行打印。
如果您不需要打印,
!?foo
搜索并立即执行它。
bind Space:magic-space # !pin<space>
我有一个秘密武器: 贝芙。
有成千上万的技巧,绝妙的技巧和有效的食谱,大多数时候都可以放在一行上。
我最喜欢的一个(但是我作弊了一点,因为我使用了现在大多数Unix系统上都安装了Python的事实):
alias webshare='python -m SimpleHTTPServer'
现在,每次您键入“ webshare”时,当前目录都可以通过端口8000访问。当您想与没有usb密钥或远程目录的本地网络上的朋友共享文件时,这真是太好了。流视频和音乐也可以。
当然,经典的叉子炸弹虽然完全没有用,但仍然很有趣:
$ :(){ :|:& };:
不要在生产服务器中尝试...
python -m SimpleHTTPServer
(除非我遗漏了原始命令所做的花哨
您可以将watch命令与另一个命令结合使用以查找更改。例如,当我测试路由器时,我想获取有关信噪比等信息的最新数字。
watch --interval=10 lynx -dump http://dslrouter/stats.html
type -a PROG
为了找到所有可使用PROG的地方,通常在〜/ bin中的某个地方,而不是在/ usr / bin / PROG中一个可能的地方。
PATH
则会显示每个位置。
我喜欢用echo构建命令并将它们通过管道传递给外壳程序:
$ find dir -name \*~ | xargs echo rm
...
$ find dir -name \*~ | xargs echo rm | ksh -s
为什么?因为它使我可以在开始之前先了解要做什么。这样,如果我遇到一个可怕的错误(例如删除我的主目录),我可以在它发生之前将其捕获。显然,这对于破坏性或不可撤销的行为最为重要。
$ find dir -name \\*~ -exec rm {} +
下载大文件时,我经常这样做:
while ls -la <filename>; do sleep 5; done
完成后(或者如果ls
返回非零),只需按ctrl + c即可。它与watch
程序类似,但是它使用外壳程序,因此可以在没有watch
。
另一个有用的工具是netcat或nc
。如果您这样做:
nc -l -p 9100 > printjob.prn
然后,您可以在另一台计算机上设置打印机,但可以使用运行netcat的计算机的IP地址。发送打印作业后,运行netcat的计算机会接收到该打印作业并将其转储到中printjob.prn
。
wget
?
watch ls -la <filename>
(如果您不喜欢默认值2秒,请使用-n5)。
watch
并非在所有平台上都可用,例如Solaris,Mac OS X等。@Porges,不确定您的意思。wget还能在端口上监听吗?
在树形层次结构中彼此分开的多个位置中使用多个目录时,导航的一种首选方法是使用acf_func.sh(下面列出)。定义后,您可以执行
光盘-
使用数字菜单查看最近目录的列表
光盘-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
$ echo !$ !-2^ *
Alt+ Ctrl+ e
$ echo aword someotherword *
Ctrl+ _
$ echo !$ !-2^ *
Ctrl+ x,*
$echo !$ !-2^ LOG Makefile bar.c foo.h
&C。
Enter
:)
我一直很喜欢:
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
。
screen
,默认情况下ctrl-A也是转义键。我将其重新映射到ctrl-X .screenrc
,但是我不是emacs用户。
pbcopy
这将复制到Mac系统剪贴板。您可以将命令通过管道传递给它...尝试:
pwd | pbcopy
alias pbcopy='xsel --clipboard --input'
和 alias pbpaste='xsel --clipboard --output'
$ 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
history 10
而不是history | tail -10
(tail -n 10
由于不赞成使用该语法,因此应使用)。
与上述类似,我目前最喜欢的是击键[alt]。(Alt和“。”键在一起)与$!相同!(插入上一个命令的最后一个参数),除了它是立即数并且对我来说更容易键入。(仅不能在脚本中使用)
例如:
mkdir -p /tmp/test/blah/oops/something
cd [alt].
使用&&命令将多个命令串在一起:
./run.sh && tail -f log.txt
要么
kill -9 1111 && ./start.sh