geekdoc-linux-zh/docs/linux-101-hack/linux-101-hack_07.md

7.2 KiB
Raw Permalink Blame History

第七章 - 历史命令

这一部分介绍了三个关于history的技巧, 或是介绍.

用好了历史命令, 会让你的工作效率大大增加!

Hack-52 History 命令

History 命令

你敲的每一个命令都会被忠实地记录下来 --- 我.

上面说的也不完全对啦, 因为这个"忠实"会被各种方法破解...

首先你要有一个历史记录的概念, 然后你要知道这些记录存放到哪儿, 最后你要知道这些记录可以被删除, 修改.

搜索历史命令

快捷键 Ctrl + r

非常建议你使用这个命令, 因为当你曾经输过一个很长的命令之后, 当你再次想输入这个命令的时候, 你就可以按下这个快捷键, 然后键入那条长命令的关键词, 然后就会显示出含有那个关键词的命令, 每次按下这个键都会再往上搜一个.

( 还有一些其他的快捷键, 在我的博客上: HERE )

重复上一次的命令

  1. 向上的方向键
  2. 两个叹号: !!
  3. 还有这个: !-1
  4. 快捷键Ctrl+p

最好用的还是方向键, 不是么~

从历史记录中执行某个命令

还是沿袭上一个中的!-n模式, 其中n是一个编号.

# history | more
1 service network restart
2 exit
3 id
4 cat /etc/redhat-release
# !4
cat /etc/redhat-release 

作者给出的例子中, 执行了编号为4的命令.

执行曾经的命令中特定开头的

假设你的部分历史命令如下:

 1719  find . -type f 
 1720  find . -type f | cpio -o > test.cpio
 1721  find .  | cpio -o > test.cpio
 1722  ls
 1723  l
 1724  du -h 

那么, 怎样重复执行 1721 条呢? 除了利用!-1721这么麻烦的方法, 我们还可以用!f这样的姿势.

因为开头的f是离着最后一条命令最近的, 所以!f就执行了它.

清空历史记录

 history -c 

从历史记录中截取参数

在下面的例子中, !!:$ 等价于上一条命令的最后一个参数:

# ls anaconda-ks.cfg
anaconda-ks.cfg
# vi !!:$
vi anaconda-ks.cfg 

下面的例子中, !^则等价于上一条命令的第一个参数:

# cp anaconda-ks.cfg anaconda-ks.cfg.bak
anaconda-ks.cfg
# vi !^
vi anaconda-ks.cfg 

从特定的历史记录中截取特定的参数

下面的例子中, !cp:2 等价于当前历史记录中, 最后一个以cp开头的命令的第二个参数; !cp:$则等价于当前历史记录中最后一个以cp开头的命令的最后一个参数.

是不是有点啰嗦...

# cp ~/longname.txt /really/a/very/long/path/long-
filename.txt
... ... ...
# ls -l !cp:2
ls -l /really/a/very/long/path/long-filename.txt
# ls -l !cp:$
ls -l /really/a/very/long/path/long-filename.txt 

Hack-53 和历史命令相关的变量

和历史命令相关的变量

在历史记录中显示时间

我们可以用HISTTIMEFORMAT这个变量来定义显示历史记录时的时间参数:

➤ export HISTTIMEFORMAT='%F %T '
➤ history 
... ... ...
 1740  2016-01-05 22:45:28 man history 
 1741  2016-01-05 22:45:33 export HISTTIMEFORMAT='%F %T'
 1742  2016-01-05 22:45:34 history 
 1743  2016-01-05 22:45:38 export HISTTIMEFORMAT='%F %T '
 1744  2016-01-05 22:45:40 history 
➤ 

你也可以用下面的别名来定义显示历史命令的数量:

alias h1='history 10'
alias h2='history 20'
alias h3='history 30' 

改变历史记录的大小限制.

!/.bashrc中有这两个变量控制者 bash 储存的历史命令的数量:

# vi ~/.bash_profile
HISTSIZE=450
HISTFILESIZE=450 

他们的含义就跟他们的名字一样.

HISTFILE改变存放历史命令的文件.

# vi ~/.bash_profile
HISTFILE=/root/.commandline_warrior 

( 都是些没有太多用处的东西, 尽管可定制化水平很高...

HISTCONTROL来删除重复的历史记录

下面的例子中, 有三个pwd命令, 那么在history中就会显示三次pwd, 有点不那么人性化.

# pwd
/
# pwd
/
# pwd
/
# history | tail -4
44 pwd
45 pwd
46 pwd
47 history | tail -4 

所以我们可以这样修改:

export HISTCONTROL=ignoredups 

然后就不会出现相邻的重复记录了~

在历史命令中去重

如果你还嫌弃历史记录中的那些不相邻的重复记录, 你可以用这个:

export HISTCONTROL=erasedups 

不记录某些命令

(这个一般是默认的)

export HISTCONTROL=ignorespace 

这样历史记录中就不会储存以空格开头的命令了.

禁止记录历史命令

如果你不想记录任何历史命令的话, 可以这样做:

export HISTSIZE=0 

把历史命令记录的大小设置为0

( 还可以把历史记录的保存文件改成/dev/null, 殊途同归 ~)

不记录某些命令 II

export HISTIGNORE="pwd:ls:ls ltr:" 

这种方法的效果是, 历史记录不会记录这几个命令.

扩展阅读

15 个例子

忽然想到, 这些扩展阅读也都是英文的啊.... 不知道各位看官有没有兴趣看呢?

Hack-54 History 扩展

History 扩展

用这个功能可以选择特定的历史记录, 不论是修改还是立即执行, 都可以完成.

这个扩展以!(叹号)开头.

  • !! 重复上一条命令
  • !10 重复历史记录中第 10 条命令
  • !-2 重复历史记录中倒数第二条命令
  • !string 重复历史记录中最后一条以string开头的命令
  • !?string 重复历史记录中最后一条包含string的命令
  • ^str1^str2^ 把上一条命令中的str1替换成str2, 然后再执行
  • !!:$ 扩展成上一条命令的最后一个参数 ( 完全可以用Alt+.快捷键啊! )
  • !string:n 扩展成最后一条以string开头的命令的第n个参数....

!?string栗子

假设你曾经执行过这样一条命令:

$ /usr/local/apache2/bin/apachectl restart 

然后过了一会儿你想重复这个命令, 然后你这样做:

$ !apache
-bash: !apache: event not found 

哔~ 找不到!

当然, 因为曾经的那条命令并不是以apache开头的, 但是:

$ !?apache
/usr/local/apache2/bin/apachectl restart 

这样就会执行, 因为这条命令包含了apache这个字.

^str1^str2^栗子

作者给的例子太牵强, 我给个实用的:

➤ cat cal_random.sh 
#!/bin/bash
echo hi
test(){
    for i in {1..9};do
        echo $i;
    done
}
... ... ...
exit 0
➤ ^cat^less
less cal_random.sh 
➤ 

哈, 这个也不实用, 因为要达到这样的目的有好多方法, 而替换这一种实在太麻烦了.

!!:$栗子

废话不说, 上代码 ~!

➤ cp cal_random.sh cal_random.sh.bak
➤ head -n 2 !!:$
head -n 2 cal_random.sh.bak
#!/bin/bash
echo hi
➤ 

在这个例子中, !!:$被扩展成了上一条命令的最后一个参数, 可以理解为正则的$表示最后一样.

!string:n 栗子

曾经执行了这样一条命令

cat file1 file2 file3 

然后你想截取其中的第二个参数,

那么你就可以这样(确保最后一条以 cat 开头的命令是它):

ls !cat:2 

上面这些东西用好了真的很方便! 尽管我一直用快捷键...