使用Bash您最喜欢的命令行技巧是什么?[关闭]


156

我们都知道如何使用<ctrl>-R反向搜索历史记录,但是<ctrl>-S如果设置了,您是否知道可以使用正向搜索stty stop ""?另外,您是否曾经尝试运行bind -p来查看列出的所有键盘快捷键?默认情况下,Mac OS X上有超过455个。

使用bash,您最喜欢的晦涩trick俩,键盘快捷键或购物配置是什么?


2
请改写这个词,说“您最喜欢的是什么”。这样一来,人们几乎可以像投票一样投票表决特定的答案。
SCdF

>请改写这个词,说“您最喜欢的是什么”。做完了
Martin Klinke,

1
这个问题有一个StackOverflow克隆:commandlinefu.com
rkb

在这455个默认键绑定中,只有232个做了“自我插入”(“键入此键”)以外的操作:$ bind -p | grep -v self-insert | wc
Ed Brannin 09年

这里有一些整洁的东西。但应注意的是,只有当bash处于emacs模式时,它们中的许多功能才起作用...

Answers:


157

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

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


12
太棒了!现在,我需要尝试并记住这一点。
乔恩·埃里克森

9
只是指出,要进行相反操作(从.cpp-old到.cpp),您可以执行cp /home/foo/realllylongname.cpp{-old,}
Michael Ekoka 2010年

回想起来如此明显,但是我不记得我一个人做。谢谢!
Zecc 2010年

150
cd -

它在命令行上等效于后退按钮(将您带到您所在的上一个目录)。


6
我自己更喜欢使用pushdpopd维护目录堆栈。
Alex M

21
但是,即使您不记得使用push,“ cd-”也具有工作的优势。
塞尔吉奥·阿科斯塔

10
值得一提的是,“ cd”会将您带到主目录。
dr-jan

有趣的是,这没有出现在man cdcd --help(至少是我的)中。
HalilÖzgür

135

另一个最爱:

!!

重复上一个命令。最有用的形式:

sudo !!

81
它具有使您听起来也真的很生气的额外好处。“计算机,执行此操作。” “拒绝访问”。“做吧!!”
尼克

这是鲜为人知的!:-)
hoyhoy

10
您可以执行类似的操作:mkdir testdir; cd !$..运行cd [last word of previous line](在示例中cd testdir
dbr

13
让我成为三明治苏多!
Kibbee

如果您喜欢!!,!$和!-1:^ foo ^ bar,则还将“绑定Space:magic-space”。 stackoverflow.com/questions/603696/…–
Yoo

81

我最喜欢的是'^ string ^ string2',它接受最后一条命令,用string2替换string并执行

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

Bash命令行历史记录指南


这是非贪婪的。我如何使其贪婪?
Altreus,

9
!!:gs/ehco/echo/
andre-r

该指南的第二页至关重要
jmoz 2010年

1
@ andre-r:!!:gs/ehco/echo/执行全局搜索并替换最后一条命令(!!stackoverflow.com/questions/68372/…中授予)。这不等于^ehco^echo仅仅替换一个“ ehco”实例,而是一个更准确的响应!!:s/ehco/scho
Iceland_jack

64

改名

例:

$ 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

好有用


3
哇,这些年来,我一直都是笨蛋,使用basename,mv和{}技巧来做到这一点。/ foreheadsack。
Gregg Lind

7
重命名并不像其他帖子一样专门针对bash / readline。

1
在大多数情况下,来自zsh发行版的zmv更好。
ZyX

util-linux-ng也有一个重命名命令,它不同于此答案中提到的命令。这里描述的命令实际上是mmv
Cristian Ciupitu

60

我是!$!^!*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 !*。也可以将其推广为“ nth参数”,如下所示:

$ 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

'echo !! 2'对我不起作用,从后来的帖子中我看到我认为应该是:'echo!:
2'– user13060

8
在.bashrc和任何!上添加“ bind space:magic-space”!当您按下空格时,组合会自动展开。
Yoo

47

运行命令时,有时我想使用前面的参数运行命令。为此,您可以使用以下快捷方式:

$ 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 ""

6
我找到“ Alt-”。重复上一个命令的最后一个单词比“ !!:*”要好得多。
Weidenrinde

历史记录的补充:1.定期保存历史记录(如果同时打开多个外壳,则使用-a)export PROMPT_COMMAND =“ history -a” 2.别名,用于从其他外壳读取历史记录。别名-h ='history -n; 历史| grep的“
Weidenrinde

不需要HISTIGNORE =“ [] *”,因为您的HISTCONTROL = ignoreboth应该做同样的事情
Weidenrinde

历史上的另一件好事:export HISTTIMEFORMAT =“%Y-%m-%d%H:%M:%S:”
Weidenrinde

要节省“ cd !!:*”的一些击键,请尝试“ cd!$”。“!$”将被解释为您上一个命令的最后一个参数。
蒂姆·斯图尔特

43

如何列出当前目录中的子目录?

ls -d */

这是一个简单的技巧,但是您不知道我需要多少时间才能找到那个!


2
优秀的!这些年来,我能想到的最好的就是alias lsd='ls -F | grep --color /',它会列出相同的内容,但是方式更la脚。但是,为了便于解析,它会在每行列出一个目录。我已修改您的命令以执行相同的操作:ls -d1 */
Artem Russakovskii 2009年

这是如何运作的?“ ls -d”仅列出。(很奇怪),但是“ ls -d * /”有效。
Yoo

1
有点棘手...“ ls -d”类似于“ ls -d ./”,“ls -d /”类似于“ ls -d ./*/”。'-d'开关设置'ls'tu仅列出目录条目,但是如果不给它参数,它将使用当前目录作为参数,因此它只有*。目录列表...
edomaur

1
我不敢相信我从来没有发现过这个。大提示。
尼克·迪克森

无话可说,哇!:)
dimba 2011年

41

ESC.

插入最后一个bash命令中的最后一个参数。它比您想的要方便得多。

cp file /to/some/long/path

光盘 ESC.


这对我有用(打击)。请注意,您按了esc键,然后按了句号键。没有连字符或任何东西。
咆哮者”

9
也alt-。是同一回事。
马克·贝克

是的,仅Bash。但是<esc>(或Alt-或Meta-)_绑定到相同的功能,并且<esc> -_也可以在vi模式下工作。
尼克·迪克森

@hendry在我的zsh中确实有效。也许您使用vi模式?
ZyX

使用kbd-tag来敲击键盘:<kbd> ESC </ kbd>(但与代码格​​式/缩进一起使用效果不佳)。
用户未知,

36

当然可以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脚本指南》中有更多示例。


35

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

它召唤众神以一种方便阅读的格式列出最近修改的文件的能力。


6
让我想起了另一个完全无用但又有趣的命令: ls -bart -simpson -ruls。S,ICNR
filiprem 2010年

“ ls -tor”也很有用,因为您可以快速找到大文件。而且,雷电之神的名字在瑞典的原始拼写实际上是“ Tor”。
达拉

在丹麦语中,您可以使用ls -lort丹麦语“粪便”一词。省略任何团体,而不会发怒:)
杰斯珀·罗恩·詹森(JesperRønn-Jensen)2010年

1
也可以说像“ ls -lotr”,这显然与托尔金和《指环王》有关:)
ADEpt 2010年

28

更多新颖,但这很聪明...

使用的前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

1
这是一个简短,快速的版本:history | awk 'BEGIN {FS="[ \t]+|\\|"} {print $3}' | sort | uniq -c | sort -nr | head
已暂停,直到另行通知。

25

^ R反向搜索。按^ R,键入要匹配的上一个命令的片段,然后按^ R,直到找到所需的命令。然后,我不必记住仍在我的历史记录中的最近使用过的命令。不仅仅限于bash,还包括:^ E表示行尾,^ A表示行首,^ U和^ K分别删除光标之前和之后。


2
由于某种原因,我永远不记得^ U。也没有单词删除删除快捷方式吗?
hoyhoy

1
^ W删除光标之前的单词。(请随时使用此选项编辑答案。)
Jon Ericson

2
^ R是如此有用,以至于在问题中提到它:)
马克·贝克

20

我经常为vi,ls等使用别名,但有时您想转义别名。只需在前面的命令中添加反斜杠即可:

例如:

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

不错,不是吗?


您也可以运行command-请SHELL BUILTIN COMMANDS参阅Bash手册。
Iceland_jack

17

这是几个配置调整:

~/.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

+1 bash_completion非常棒
充满魅力

在Mac上,可以使用以下箭头键启用“历史记录”搜索:绑定'“ \ e [A”':history-search-backward绑定'“ \ e [B”':history-search-forward
Asmus

17

我经常使用以下内容:

:p用于显示历史记录结果的修饰符。例如

!!:p

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

与此相类似:

!?foo?:p

将在您的历史记录中搜索包含字符串'foo'的最新命令并进行打印。

如果您不需要打印,

!?foo

搜索并立即执行它。


2
除了使用:p,您还可以使用magic-space:stackoverflow.com/questions/603696/…–
Yoo

扩大历史控制范围而无需在bashrc中运行confiure magick空间bind Space:magic-space # !pin<space>
SergioAraujo 2011年

16

我有一个秘密武器: 贝芙。

有成千上万的技巧,绝妙的技巧和有效的食谱,大多数时候都可以放在一行上。

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

alias webshare='python -m SimpleHTTPServer'

现在,每次您键入“ webshare”时,当前目录都可以通过端口8000访问。当您想与没有usb密钥或远程目录的本地网络上的朋友共享文件时,这真是太好了。流视频和音乐也可以。

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

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

不要在生产服务器中尝试...


我想我不应该进行网络共享/
Yoo

我想您可以将命令简化为python -m SimpleHTTPServer(除非我遗漏了原始命令所做的花哨
JesperRønn-Jensen2010年

嗯 在生产服务器上,分叉炸弹将被操作系统抑制。任何用户可以创建的进程数量都有限制。
Donal Fellows 2010年

3
@Donal:您应该尝试一下并报告您的发现。
Michael Foukarakis

12

您可以将watch命令与另一个命令结合使用以查找更改。例如,当我测试路由器时,我想获取有关信噪比等信息的最新数字。

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

watch命令真的很棒。大约五年前,我首先在Linux Server Hacks一书中读到了有关内容。谁知道它的存在?
hoyhoy

11
“观看”与bash有什么关系?
Artem Russakovskii 09年

11
type -a PROG

为了找到所有可使用PROG的地方,通常在〜/ bin中的某个地方,而不是在/ usr / bin / PROG中一个可能的地方。


1
它还会告诉您它是函数还是别名。如果它在您的多个位置,PATH则会显示每个位置。
暂停,直到另行通知。

11

我喜欢用echo构建命令并将它们通过管道传递给外壳程序:

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

为什么?因为它使我可以在开始之前先了解要做什么。这样,如果我遇到一个可怕的错误(例如删除我的主目录),我可以在它发生之前将其捕获。显然,这对于破坏性或不可撤销的行为最为重要。


1
您可能要使用find -print0和xargs -0来避免文件和文件夹中包含空格的问题。
neu242

或者避免创建和使用名称中带有空格的文件和文件夹。;-)显然,如果您使用的是用户生成的名称,那么您的建议至关重要。
乔恩·埃里克森

4
当您只需删除“ echo”时,为什么还要附加“ | ksh -s”?
Yoo

无需使用GNU查找:$ find dir -name \\*~ -exec rm {} +
bobbogo 2011年

10

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

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
porges

尝试watch ls -la <filename>(如果您不喜欢默认值2秒,请使用-n5)。
Ted Percival

1
@Ted watch并非在所有平台上都可用,例如Solaris,Mac OS X等。@Porges,不确定您的意思。wget还能在端口上监听吗?
dreamlax


10

在树形层次结构中彼此分开的多个位置中使用多个目录时,导航的一种首选方法是使用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

10

在击中可怕的回车之前先展开复杂的行

  • Alt+ Ctrl+ e- 壳扩张线(可能需要使用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。


+1,我总怕压的Enter:)
若昂·波特拉

这些都不知道。撤消是一个杀手。适用于任何命令行编辑。
Philippe A.

9

我一直很喜欢:

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


Home和End执行与crtl-A和ctrl-E相同的操作。
davidfg4

这对于没有归位键和结束键的Mac笔记本电脑有帮助。
jamesh

不幸的是screen,默认情况下ctrl-A也是转义键。我将其重新映射到ctrl-X .screenrc,但是我不是emacs用户。
系统暂停

与cdable_vars选项有些相关,还有CDPATH环境变量。但这工作原理有所不同,因为您设置了父目录,就像在PATH中一样。使用cdable_vars,您可以获得更多控制权。
Zecc 2010年

1
快捷键列表的更多信息:CTRL + K删除从光标到行尾的所有内容,CTRL + U删除光标之前的所有内容,ALT + F / ALT + B向前/向后移动一个单词(或CTRL +向左键/ CTRL +向右箭头)。cdable_vars +1!
Philippe A.

8

pbcopy

这将复制到Mac系统剪贴板。您可以将命令通过管道传递给它...尝试:

pwd | pbcopy


注意!这是Mac专用的命令。
达拉2010年

这些不是: alias pbcopy='xsel --clipboard --input'alias pbpaste='xsel --clipboard --output'
wawawawa 2011年

7
$ 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 -10tail -n 10由于不赞成使用该语法,因此应使用)。
暂停,直到另行通知。

7

在命令行中使用“ set -o vi”,或者在.bashrc中使用更好的设置,可以使您进入命令行的vi编辑模式。您从“插入”模式开始,因此可以像往常一样键入和退格,但是如果犯了“大”错误,则可以按esc键,然后像在vi中一样使用“ b”和“ f”来移动。连续变词。在调出要更改的历史记录命令后特别有用。


7

与上述类似,我目前最喜欢的是击键[alt]。(Alt和“。”键在一起)与$!相同!(插入上一个命令的最后一个参数),除了它是立即数并且对我来说更容易键入。(仅不能在脚本中使用)

例如:

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

也可以尝试将其与Alt- [0-9]组合(按第一个组合,然后释放,然后第二个组合)。例如,如果最后一个命令是“ mv foo bar”,则为“ Alt-0 Alt-”。给出“ mv”,“ Alt-1 Alt-”。给出“ foo”,“ Alt-2 Alt-”。和基本的Alt-。都给“酒吧”,等等
山姆·斯托克斯

1
也可以尝试按Alt-。不止一次(或按住Alt键,将其按住不放,多次按dot,然后释放Alt键),这类似于多次按Ctrl-R。
Yoo

7

使用&&命令将多个命令串在一起:

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

要么

kill -9 1111 && ./start.sh

1
如果一个失败,则将不会执行另一个命令(快速失败,就像在编程中一样)
Frederic Morin

1
相反是使用逻辑或“ ||” 其中仅当左侧为假时才执行右侧。示例:<code> command_1 || command_2 </ code>
dala 2010年
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.