学习T神的《像黑客一样使用Linux命令行》

po主Linux/Unix奇菜无比,看到Toy大神的PPT《像黑客一样使用 Linux 命令行》画面太美,就必须学习一下。

依然是用OSX冒充Linux…

Talk is cheap…

1. 有趣的历史命令统计脚本

用简单的几行命令找出shell执行过的历史命令中出镜率最高的10个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
➜  ~  history |
> awk '{CMD[$2]++;count++;}END \
> { for (a in CMD)print CMD[a] " " \
> CMD[a]/count*100 "% " a;}' |
> grep -v "./" |
> column -c3 -s " " -t |
> sort -nr |
> nl |
> head -n10
1 265 10.3962% git
2 258 10.1216% ls
3 205 8.04237% sudo
4 166 6.51236% man
5 164 6.4339% awk
6 118 4.62927% vi
7 92 3.60926% cd
8 80 3.13849% port
9 76 2.98156% cat
10 73 2.86387% ps
  • history其实是fc -l 1的别名,而fc命令可以用来列出编辑重新执行用户过去向Shell中输入的内容;
  • 再用awk过滤并统计history的结果:取history返回值的第二列(命令名称),存入名为CMD的映射并累加重复的命令,count负责统计总命令数,统计结束后按行输出<命令执行的次数、占总命令数的百分比、该命令的名称>;
  • 再用grep -v去除那些带有'/'的目录跳转(使用grep -vE "./| \."对po主有奇效,因为po主有时会使用类似.ssh的不规范写法进入一个目录);
  • 再用column命令造一个漂亮的表格;
  • 再用sort命令排序取逆;
  • 再用nl命令给结果加上序号;
  • 再用head命令取TOP10;

于是就漂亮的统计出了我的历史记录使用结果(看到mansudo的排名就知道应该是个noob)。

2. 有用的执行的命令的修改

po主因为noob,不熟悉系统,经常在输入命令的时候出现typo…这也是没办法的事,如果重新键入,或是把历史记录掉出来再移动光标至输入错误处修改,就太麻烦了,还好shell可以帮我:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 一删
➜ ~ finder ~ -iname "using-cli-like-a-hacker.md"
zsh: command not found: finder
➜ ~ ^er
➜ ~ find ~ -iname "using-cli-like-a-hacker.md"
/Users/zealot/blog/source/_posts/using-cli-like-a-hacker.md
# 二改
➜ ~ echo "the ordre is incorrect"
the ordre is incorrect
➜ ~ ^re^er
➜ ~ echo "the order is incorrect"
the order is incorrect
➜ ~ echo "there is a typo"
there is a typo
➜ ~ ^a^no
➜ ~ echo "there is no typo"
there is no typo
# 三全换
➜ ~ ln /opt/local/bin/hub /usr/bin/hub
ln: /opt/local/bin/hub: No such file or directory
➜ ~ ^hub^git^:G # zsh
# 或!:gs/hub/git
➜ ~ ln /opt/local/bin/git /usr/bin/git

Toy神的口诀是:

  • 一删(^er
  • 二改(^a^no
  • 三全换(^hub^git^:G!:gs/hub/git

3. 深入了解命令历史

3.1 历史记录属性:

1
2
3
4
5
6
7
8
9
10
11
12
# 历史记录的大小
➜ ~ echo $HISTSIZE
10000
# 历史记录保存的位置
➜ ~ echo $HISTFILE
/Users/zealot/.zsh_history
# bash
➜ ~ echo $HISTFILESIZE
10000
# zsh
➜ ~ echo $SAVEHIST
10000

3.2 查看历史记录:

1
2
3
4
5
➜  ~  history | less
# 显示前五条
➜ ~ history 5
# 在历史记录中查找
history | grep string
  • 按下[ctrl-R],进入逆向搜索历史模式:
1
2
➜  ~  history | less
bck-i-search: history |
  • 按下[ctrl+P]访问前一条命令
  • 按下[ctrl+N]访问下一条命令

3.3 关于!的历史引用

  • 使用!!执行上一条命令:

这个很常用,特别是在没有权限的时候配合sudo使用:

1
2
3
4
5
6
7
8
➜  ~  port -v selfupdate
...
failed: Permission denied
...
➜ ~ sudo !!
➜ ~ sudo port -v selfupdate
Password:
...
  • 使用!foo执行以foo开头的命令:
1
2
➜  ~  !port
➜ ~ port outdated
  • 使用!?foo执行包含foo的命令:
1
2
➜  ~  !?out
➜ ~ port outdated
  • 使用!n执行历史记录中第n个命令(可能会很早):
1
2
➜  ~  !9
➜ ~ pwd
  • 使用!-n执行倒数第n个命令(比较常用):
1
2
➜  ~  !-9
➜ ~ echo $HISTSIZE

注:!-1 == !!

  • 使用!#引用当前行
1
2
➜  ~  echo !#
➜ ~ echo echo

3.4 历史命令的Word选取

历史命令Word选取图

  • 使用!$得到上一条命令的最后一个参数:
1
2
3
4
➜  ~  mkdir videos
➜ ~ cd !$
➜ ~ cd videos
➜ videos

也可以通过快捷键[alt+.]获得。

注:OSX上需要设置在Terminal->Terminal->Preferences->Settings->Keyboard中设置“Use option as meta key”,在iTerm上通常设置“left option key as +Esc”。

  • 使用!^得到上一条命令的第一个参数:
1
2
3
4
5
6
7
8
9
➜  ~  ls /usr/share/doc /usr/share/man
/usr/share/doc:
...

/usr/share/man:
...
➜ ~ cd !^
➜ ~ cd /usr/share/doc
➜ doc

也可以通过快捷键[Ctrl+Alt+Y]获得。(OSX上似乎不行…求指点)

* 使用!:n得到上一条命令第n个参数:

1
2
3
➜  ~  touch foo.txt bar.txt baz.txt
➜ ~ vim !:2
➜ ~ vim bar.txt
  • 使用!:x-y得到上一条命令从第x到第y的参数:
1
2
3
➜  ~  touch foo.txt bar.txt baz.txt
➜ ~ rm !:1-3
➜ ~ rm foo.txt bar.txt baz.txt
  • 使用!:n*得到上一条命令中从第n个参数开始到最后的参数:
1
2
3
➜  ~  cat /etc/resolv.conf /etc/hosts /etc/hostname
➜ ~ vim !:2*
➜ ~ vim /etc/hosts /etc/hostname
  • 使用!*得到上一条命令的所有参数:
1
2
3
➜  ~  ls src dst
➜ ~ cp -r !*
➜ ~ cp -r src dst

关于Word选取,需要记住的是:

  • n:第n个参数;
  • ^|$:第一个参数|最后一个参数;
  • n*:从第n个参数开始取到最后的参数;
  • x-y:从第x个参数开始取到第y个参数;

3.5 历史命令的修饰符

  • 使用:h选取路径的开头部分:
1
2
3
4
➜  ~  ls /usr/share/doc/bash/bash.html
/usr/share/doc/bash/bash.html
➜ ~ ls !$:h
➜ ~ ls /usr/share/doc/bash

相当于使用dirname命令。

  • 使用:t选取路径的结尾部分:
1
2
3
4
➜  ~  wget http://nginx.org/download/nginx-1.7.2.tar.gz
...
➜ ~ tar zxvf !$:t
➜ ~ tar zxvf nginx-1.7.2.tar.gz

相当于使用basename命令。

  • 使用:r选取文件名:
1
2
3
4
5
6
➜  ~  wget http://nginx.org/download/nginx-1.7.2.zip
...
➜ ~ unzip nginx-1.7.2.zip
...
➜ ~ cd !$:r
➜ ~ cd nginx-1.7.2
  • 使用:e选取扩展名:
1
2
3
4
5
6
7
8
➜  ~  echo filname.extension
filname.extension
➜ ~ echo !$:e
➜ ~ echo extension
#bash
.extension
# zsh
extension
  • 使用!:p打印命令:
1
2
3
4
➜  ~  echo *
...
➜ ~ !:p
➜ ~ echo *
  • 使用:s做替换:
1
2
3
4
➜  ~  echo this that
this that
➜ ~ !:s/is/e
➜ ~ echo the that
  • 也就是前面提到的“二改”:

    1
    2
    3
    4
    ➜  ~  echo this that
    this that
    ➜ ~ ^is^e
    ➜ ~ echo the that
  • 使用:g做全局操作:
1
2
3
4
➜  ~  echo abcd abef
abcd abef
➜ ~ !:gs/ab/cd
➜ ~ echo cdcd cdef
  • 也就是前面提到的“三全换”:

    1
    2
    3
    4
    ➜  ~  echo abcd abef
    abcd abef
    ➜ ~ ^ab^cd^:G
    ➜ ~ echo cdcd cdef
  • 使用:u将命令改为大写(zsh):
1
2
3
4
5
➜  ~  echo $histfile

➜ ~ echo !$:u
➜ ~ echo $HISTFILE
/Users/zealot/.zsh_history
  • 使用:l将命令该为小写(zsh):
1
2
3
4
5
➜  ~  echo $HISTORY

➜ ~ echo !$:l
➜ ~ echo $history
...

关于修饰符,要记住的是:

  • h|t:选取路径的开头|结尾;
  • r|e:选取文件名|扩展名;
  • p:打印命令;
  • s:替换操作;
  • g:全局操作;
  • u|l:将参数改为大写|小写;

综上:

历史命令结构展开图

4. 常备锦囊,内藏妙计

  • 使用alias -s定义后缀别名(zsh):
1
2
3
➜  ~  alias -s py=python3
➜ ~ test.py
python3 test.py
  • 使用 {} 构造字符串:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
➜  ~  cp grade.txt{,.bak}
➜ ~ cp grade.txt grade.txt.bak
➜ ~
➜ ~ vim {a,b,c}file.c
➜ ~ vim afile.c bfile.c cfile.c
➜ ~
➜ ~ wget http://linuxtoy.org/img/{1..5}.jpg
1.jpg 2.jpg 3.jpg 4.jpg 5.jpg
➜ ~
➜ ~ echo {01..5}.txt
01.txt 02.txt 03.txt 04.txt 05.txt
➜ ~
➜ ~ echo 0{1..5}.txt
01.txt 02.txt 03.txt 04.txt 05.txt
➜ ~
➜ ~ echo {1..10..2}.txt
1.txt 3.txt 5.txt 7.txt 9.txt
➜ ~
➜ ~ echo {1..10..-2}.txt
9.txt 7.txt 5.txt 3.txt 1.txt
➜ ~
➜ ~ echo {9..1..-2}.txt
1.txt 3.txt 5.txt 7.txt 9.txt
➜ ~
➜ ~ mkdir -p 2014/{01..12}/{baby,photo}
  • 使用``或$()做命令替换:
1
2
3
4
➜  ~  echo $(date +'%Y%m%d')
20140707
➜ ~ echo `date +'%Y%m%d'`
20140707
  • 使用变量保存信息:
1
2
3
➜  ~  LOG=/var/log/emerge.log
➜ ~ head $LOG
➜ ~ grep -i compiling $LOG
  • 使用 for … in 重复执行命令:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
➜  ~  figlet -f font-type-1 Linux # (1)
➜ ~ figlet -f font-type-2 Linux # (2)
➜ ~ figlet -f font-type-3 Linux # (3)
➜ ~ ...
➜ ~
➜ ~ cd /usr/share/figlet
➜ ~ for font in *.flf
for> do
for> echo $font
for> figlet -f $font Linux
for> done
...
➜ ~ for font in *.flf; do echo $font; figlet -f $font Linux; done
➜ ~
➜ ~ for dev in /dev/sd{a..d}
for> do
for> hdparm -t $dev
for> done

5. 其他

5.1 重要原则

  • Type less, accomplish more (少打多做);
  • DRY, don’t repeat yourself (不要重复你自己);
  • Care about your tool (关心你的工具);

5.2. 此外…

  • Tab补全;
  • 使用通配符 (*, ?, [a-z], [0-9]);
  • 用快捷键编辑命令行;
  • 字符串处理;
  • 复合命令 (;, &&, ||);

5.3 扩展阅读:

ps: 关于awk, sed, grep等复杂命令,以后再详解。

-EOF-

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×