Contents

常用的Shell命令

The Missing Semester of Your CS Education 学习笔记

最近在看“The Missing Semester of Your CS Education”这个公开课,内容不算太难,不讲编程语言或者理论,而是讲解怎样能够构建更加便利的编程环境,如何使用像shell,git, gdb这些工具,可以当作一种查漏补缺。我才看到前两节课,主要讲shell scirpt的编写和简单的linux命令,也比较有启发,所以用这个博客记录下来。

我已经有很久没有更新博客了,毕业的时候一切都比较忙乱,上班了之后总是觉得没有什么可以写的,便一直搁置。期间忘记续了域名,掐着域名回收流入市场的时间点又抢了回来,最近刚刚重新搭建了网站,换了一个主题,自己也会尽量添加一些新鲜的内容。

Shebang line

经常看到shell脚本文件的第一行是:

1
#!/usr/local/bin/bash

,大概知道是告诉linux用来执行这个文件的程序,./script-name相当于/usr/local/bin/bash script_name,才知道这一行叫做Shebang line, 中文翻译为释伴(这也太抽象了)。

除了指定一个绝对路径外,也可以写成:

1
#!/usr/bin/env python

这样可以从系统路径里面来找程序。

设置CDPATH

跟环境变量PATH类似,CDPATHcd命令查找文件夹的路径,你可以放置一些常用的比较长的目录,比如你有一个目录叫做/home/long/dir/work,你可以这样设置:

1
2
export CDPATH='/home/long/dir'
cd work

这也方便你在同一个目录下的不同文件夹进行切换,而不用频繁的进行cd ..

shell里面的重定向

shell命令的文件描述符有0,1,2,分别表示标准输入,标准输出以及标准错误输出。常用的重定向包括 >, 覆盖输出 >>, 以及管道| 再次并不赘述。

屏蔽输出结果

写入到 /dev/null的内容都会被丢弃,因此可以起到屏蔽输出的作用

屏蔽stderr

1
find . 2>> /dev/null

屏蔽stdout和stderr

1
find . >> /dev/null 2>&1

同时输出stderr和stdout

将stdout和stderr分别重定向到不同文件

1
command  > stdout.log 2> stderr.log

合并stdout和stderr,并写入到文件。

1
command >> file 2>&1

这等同于:

1
command  &>> file

值得注意的是,如果把2>&1 放在重定向符>或者>>之前,就起不到合并写入stdout和stderr的结果,这是因为讲stderr指向stdout的输出之后,stdout的输出又被重定向到别的地方。详细的解释可以参考这个文档.

1
command  2>&1 >> file

有意思的是,用pipe来做重定向, 并且想合并上一个命令的stdout和stderr的话,2>&1 要放在 | 前面, 这等同于用|&。这是因为pipe并不会改变stdout的输出,而是连接到下一个command的输入。
tee 命令可以在terminal里显示程序的输出的同时,将output写入文件中。

1
command . 2>&1 | tee /tmp/output.txt

等同于

1
command . |& tee /tmp/output.txt

xargs结合管道进行参数传递

有一些命令不接受stdin作为输入,此时需要用xargs将管道传入的stdin转换为命令行参数。

常见的用法有:

根据名字过滤文件并进行操作:

1
find ... | grep ... | xargs ...

docker停止所有运行的container:

1
docker ps -a -q | xargs docker rm

值得一提的是,find命令的-exec也有与xargs类似的功能,示例如下:

1
find . -type f -exec ls -l {} \;

替换 substitution

变量替换 variable substitution

可以用双引号来将内容替换成变量的值:

1
2
foo=bar
echo "It's a $foo"

值得注意的是,单引号并不可以。

命令替换 command substitution

也可以用 `command` 或者$( command )将命令执行的结果保存到变量里,比如:

1
2
3
4
for file in `ls`
do
...
done

将不知道具体路径的文件拷贝到本地:

1
cp `which filename` .

相似的是,bash -c "command" 会将字符串里面的内容当作命令来执行。

docker删除运行中的container:

1
docker rmi $(docker images -q -f dangling=true)

进程替换 process substitution

<( command ) 或者 >(command) 会将命令或者前一个的执行结果存到临时文件里,并且返回这个文件的名字,因此适合用来进行文件的操作。

比如比较两个命令的输出:

1
diff <(ls dir1) <(ls dir2)

将stderr和stdout分别定向到两个命令

1
some_command > >(/bin/cmd_for_stdout) 2> >(/bin/cmd_for_stderr)

一些有用的工具

左边是`man find`的输出,右边是tldr的搜索结果

参考

  1. Illustrated Redirection Tutorial - https://web.archive.org/web/20230315225157/https://wiki.bash-hackers.org/howto/redirection_tutorial
  2. 释伴:Linux 上的 Shebang 符号(#!) https://linux.cn/article-3664-1.html
  3. What is Shebang in Linux Shell Scripting? https://linuxhandbook.com/shebang/
  4. Changelog Interviews – Episode #547 Efficient Linux at the CLI https://changelog.com/podcast/547
  5. The Missing Semester of Your CS Education: https://missing.csail.mit.edu/
  6. xargs 命令教程 https://www.ruanyifeng.com/blog/2019/08/xargs-tutorial.html