Linux/Unix 命令和用法集合

Linux/Unix 系统下的一些常用命令和用法。

常用短命令

按键 / 命令 描述
cd Home 目录
cd [folder] 切换目录
cd ~ Home 目录,例如 ‘cd ~/folder/’
cd / 根目录
ls 文件列表
ls -l 文件详细列表,一行一个文件
ls -a 列出隐藏文件
ls -1 (数字 1) 还是一行一个文件,不过只显示文件名,隐藏其他的属性
ls -lh 文件详细列表中的文件大小以更友好的形式列出
ls -R 递归显示文件夹中的内容
ls -t 按照修改时间从新到老排序
sudo [command] 以超级用户身份执行命令
open [file] 打开文件 ( 相当于双击一个文件 )
top 显示运行中的进程,按 q 终止
cat [file] 预览文件中的内容(但不编辑)
nano [file] 打开编辑
pico [file] 打开编辑
exit 退出
clear 清屏

文件和文件夹操作(file and directory)

列出文档

最常见的 ls 命令。

有用的参数:

  • -l: 一行显示一个文件,并且显示该文件的全部属性(读写权限、日期、用户等);
  • -lh:更友好的显示
  • -a: 显示隐藏文件;
  • -1(数字 1):只显示文件名,隐藏其他的属性;
  • -t:按照修改时间从新到老排序;
  • -R: 递归显示文件夹内容;

打开文档或文件夹

  • 使用 open 命令打开文件:
    open <file>
    

    在 Linux 下还有 gnome-open 命令。

  • 在终端中打开当前路径的 Finder (Mac) 或者 Nautilus (ubuntu):
    open .
    

    即后面加一个点。

统计当前目录下的文件个数

参考:wc command examples

使用 wc 命令并结合 ls 使用:

ls -l *.cpp | wc -l

-l 是统计行数。因为前面已经列出了全部的 cpp 文件,因此整个命令就是统计 cpp 文件个数。

统计文件大小

使用 du 命令。

当前整个文件夹的大小

du -sh
  • -s 是统计整个路径文件夹的大小。如果去掉它,则会用递归方式打印出每个子路径的大小。
  • -h 是输出成容易读的形式,例如 1K, 234M 等。

列出本地每个文件(夹)的大小,并按从大到小排序

du -m -d 1 | sort -rn
  • -m 是文件大小以 M 为单位;
  • -d 1 其实就等于 --max-depth=1,即统计到某一个深度值,这里的 1 就是只统计到当前这一层。如果不加上 -d,就会输出全部子路径的大小。
  • sort -rn 就是排序了,这里用了一个 pipe 将 du 的输出传递给 sort 命令。参数 -r 是倒序排列(从大到小), -n 是按照数值比较方式。

举例:列出本地最大的 10 个文件(夹)

在上面的基础上加上 head 命令:

du -m -d 1 | sort -rn | head -11

注意这里用的是 11,因为第一行是整个文件夹的大小。

也可以将这个命令放在一个 script 文件中,这样可以方便读入任意路径,并显示任意数目的文件夹。

# sort-dir-by-size.sh
#!/bin/bash 
 
if [ $# != 2 ]; then 
	echo "Incorrect number of arguments !" >&2 
	echo "USAGE: sortdirbysize [DIRECTORY] <first n directories>" 
fi 
du --block-size=1M --max-depth 1 $1 | sort -rn | head -$2 

上面的 script 输入是一个路径以及一个整数 n,打印出该路径下的前 n-1 个最大的文件(夹)。例如

./sort-dir-by-size.sh /home/linux 15

使用 dirname 获取文件夹

参考:wiki 关于 dirname 的介绍

dirname is a standard computer program on Unix and Unix-like operating systems. When dirname is given a pathname, it will delete any suffix beginning with the last slash (‘/’) character and return the result. dirname is described in the Single UNIX Specification and is primarily used in shell scripts.

dirname 用于获取一个绝对路径中的文件夹名称(即,去掉最后一个 / 后面的内容)。用法:

dirname string

例如:

$ dirname /home/martin/docs/base.wiki
/home/martin/docs

$ dirname /home/martin/docs/.
/home/martin/docs

$ dirname /home/martin/docs/
/home/martin

$ dirname base.wiki
.

$ dirname /
/

使用 basename 获取文件名

参考:wiki 关于 basename 的介绍

basename is a standard computer program on Unix and Unix-like operating systems. When basename is given a pathname, it will delete any prefix up to the last slash (‘/’) character and return the result. basename is described in the Single UNIX Specification and is primarily used in shell scripts.

basename 用于获取一个全局路径中的文件名(去掉后缀)。基本上和上面的 dirname 命令正好相反,不过用法类似。用法是:

basename string [suffix]

例如:

$ basename /home/jsmith/base.wiki .wiki
base

$ basename /home/jsmith/base.wiki ki
base.wi

$ basename /home/jsmith/base.wiki base.wiki
base.wiki

正则表达式简介(Regular Expression)

搜索等很多地方广泛用到了正则表达式。这里简单介绍一下常见的用法。

参考:

全局的元字符(Global Meta-characters)

首先介绍在任何情况下都默认有特别含义的字符(即,不只是 grep,还有类似 find, sed 等几乎所有的检索命令)。它们原本的意思会被忽略掉。如果还想要使用本来的意思,可以使用转义符\。这里笔者称它们为全局元字符。之所以笔者这么称,是因为,下面一章介绍的 BRE 中的特殊字符也叫 meta-characters,但是处理的方法却不同。为了区分,就给本章的字符取一个特别的名字。

全局元字符和它们代表的含义是:

  • . (period or dot) 匹配任意一个字符;
  • ^ (caret) 任意以该字符串开头的一行,放在字符串之前。例如,^Abc表示找出以 Abc 开头的行(在中间的就不算了).
  • $ (dollar sign) 任意以该字符串结尾开头的一行,放在字符串之后。例如,abc$表示找出以 abc 结尾的行.
  • * (star) 匹配 0 个或者多个任意字符(但是通常它不能放在开头,即它前面必须有一个字符)
  • [] (square brackets) 匹配方括号中间的某一个并且只有一个字符。例如,[abc]de 代表ade 或 bde 或 cde。另外,方括号中间如果有 -,可以代表一个范围。例如,[a-c]就代表 [abc]
  • \ (backslash) 转义符,忽略或者增加一个特殊字符的特殊含义。例如,\* 就是单纯把星号当做一个星号来处理,而不是匹配多个任意字符。当然,它在后面还有其他用法。

基础正则表达式 (Basic Regular Expression, BRE)

这就是 grep 或者 grep -e 使用的。BRE 中也有某些字符有特殊含义(除了上面给出的全局元字符外),但是它们的特殊含义默认是被忽略的。如果要使用特殊含义,必须使用转义符\。这点正好和上面的全局元字符完全相反:BRE 中是默认被忽略,必须用转义符启用特殊含义;而全局元字符是默认有特殊含义,想要关闭特殊含义才用转义符。

几个常见的 BRE 的元字符:

  • + (add) 匹配它之前的字符至少一次(一次或者多次,不能是 0 次)。例如,a\+就是至少一次的 a.
  • ? (question mark) 匹配它之前的字符任意多次(可以是 0 次,也可以是 1 次或多次)。例如,a\?就可以是空,也可以是一个或多个 a.
  • | (vertical line/bar, or pipe) 逻辑“或”,可以并列两个 pattern 到一起。例如,grep 'abc \| def' file 搜索所有 abc 或者 def,它其实就等于是 grep -e 'abc' -e 'def' file
  • () (parentheses) 将多个 patterns 放在一起各选一个。例如,(ab \| cde)fg 其实就是 abfg \| cdefg,即括号中各选一个。
  • {} (curly braces) 指定它之前的字符的重复次数,此时大括号中是数字。例如,a{2}就等于 aa,即 a 重复 2 次。

注意适用平台

BRE 的用法似乎在不同系统中会稍有不同。例如,在 Mac OSX 的 find 命令中,包括 \|{} 等多个元字符都是无法使用的(即便加上了转义符也不行),但是在 grep 命令中却都是可用的,很奇特(参见: why isn’t this regex working : find ./ -regex ‘.*(m|h)$)。一个解决方法是,使用接下来一章讲述的 ERE 就行了,它对应的在 Mac OS X 中的命令是 find -E ...

扩展正则表达式(Extended Regular Expression, ERE)

这对应的就是 grep -E 或者是 egrep。和上面的 BRE 的区别是,ERE 中默认会启动 BRE 中字符的特殊含义。即,此时就无需使用转义符 \ 了。

注意:字符在 bash 中的含义并不同

这里讲述的是元字符在正则表达式中的用法,不过这并非在 bash 中的用法。在 bash 中,某些符号可能有特殊含义,例如:

$ echo 23{4,5,14}
234 235 2314

即,curly braces 被认为“同等重要”的,会从中按照顺序依次选择。又例如,* 星号在 bash 中通常代表全部的任意文件,而不是像全局元字符那样。

搜索文件

参考:

有多种方法,不过最常见的是 find 和 locate。其中,find 命令更灵活,参数众多,但是速度慢。而 locate 最大优点是速度快,因为它是在本地的一个文件名数据库中检索的,不过它没有输入参数,每次都是在整个系统范围内检索,显然不够灵活。

locate 使用

locate filename

最好结合 sudo updatedb 来使用,后者是更新了 locate 命令检索用的本地数据库。

注意:Mac OSX 中没有 updatedb 命令,需要使用:

sudo /usr/libexec/locate.updatedb

find 使用

  find <path_to_find> -iname '<file>'

find 命令的一些参数:

  • -iname 忽略文件名大小写;
  • -type f 只检索普通文件;
  • -type d 只检索文件夹;
  • -maxdepth 2 指定检索深度。当前路径深度是 1,往下一层就是 2。默认的话是检索全部子路径,即全部深度。

正则表达式

首先,不同系统对正则表达式的支持会稍有不同。例如,Linux 和 Mac OS X 的用法不同。其次,find 命令的 GNU 版本也会影响它的参数。

一般情况下:

  • Linux 中,基础正则表达式(BRE)对应的参数是 -regextype sed,而扩展正则表达式(ERE)的参数则是 -regextype posix-extended。不过,要使用 BRE,还要后面再加上 -regex <pattern>。很多情况下,-regex 默认就是 BRE,因此前面的 -regextype sed 可以省略(注意,并非所有情况,有时候可能还是会出错)。
  • Mac OS X 中,find 默认就是 BRE,只需使用 -regex 就足够,无需额外参数。而 ERE 的话就是 find -E ...,注意 -E 参数通常是紧接着 find 命令放在开头处。

另外,前面的“注意适用平台”一章中也提到了,在 Mac 的 find 命令中,诸如 \| 之类的 BRE 中的元字符是无法使用的,此时一个解决方法是,使用 find -E 的 ERE 的用法。

举例 1:找出所有 UUID 命令类型的 JPG 文件

find . -regextype sed -regex ".*/[a-f0-9\-]\{36\}\.jpg"

每一个 UUID 是 36 个字符组成的,包括字母(只有a-f,因为是十六进制),数字(0-9)和 dash 符号,例如 81397018-b84a-11e0-9d2a-001b77dc0bed。上面命令中,[] 给出了字符范围和数字范围,大括号 {} 则是重复次数。

值得注意的是,上面例子中的第一个 / 是因为 find 命令检索的路径是全局路径。即,它找到的每个文件名前面都必定有 /,即便是在当前目录下也是类似 ./abc.txt 这样。这点很重要。例如,如果想要搜索以 Note 或者 note 开头的文件,命令是:

find <path> -regex ".*/Note\|.*/note"

举例 2:结合 find 和 sed 命令来修改文件内容

sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响。它经常被用来批量修改文件中的内容。

将一个文件中的某个老的字符串全部替换为新的字符串:

sed -i 's/old_string/new_string/g' filename

这里,/g 指代全局替换,还可以使用 /1, /2 这种,表示只替换第1次或者第2次出现的字符串。

可以结合 find 和 sed 使用,用于找出某些特定文件并在其中做某些修改。例如,下面是 Mac 中在 .c 或者 .cpp 文件中做修改:

sed -i 's/oldstr/newstr/g' `find -E . -maxdepth 1 -type f -regex '.*.c|.*.cpp'`

这里使用引号 `` 括住了 find 命令,表示将另一个命令的全部结果打包作为另一个命令的一个参数。

注意:find 中的正则表达式是严格匹配的

其实 find 的正则表达式使用起来挺麻烦的,限制很多,并且匹配形式不是很好掌握。“严格匹配”的意思通常是说,你知道你要检索的文件名严格的是什么样子的,例如长度、构成等。就像前面“举例 1:找出所有 UUID 命令类型的 JPG 文件”的例子一样,已知了 UUID 文件名的严格构成。如果你只是想要搜索包括某个字符的文件的话,使用 -name 参数就足够了,无需使用正则表达式。

搜索文件中的内容

最常见的就一个 grep 命令。用法就下面三种:

grep [options] <pattern> <file>
grep [options] -e <pattern> <file>
grep [options] -f <pattern_file> <file>

几点说明:

  • grep 会将 pattern 看做看作正则表达式(regular expression),例如 * 就是匹配任意长度字符串,. 就是匹配任意一个字符,等等。详细介绍见下一章。
  • grep 默认会输出匹配的全部行,其中包括匹配文件名和该行中和 pattern 匹配的附近的内容。
  • 这里的 <file> 可以是一个或多个文件,例如 grep 'abc' file1 file2;另外也可以是路径名(需要结合 -r 的参数使用)。
  • grep -E 其实就完全等于 egrep 命令,而 grep -f 就完全等于 fgrep 命令。

grep 三种用法的区别

  • 什么参数都没有时,默认就只有一个 pattern。
  • -e: 和上面没有参数的区别是,每一个 -e 可以指定一个 pattern。例如可以这样:grep -e p1 -e p2 file,这样就可以从 file 中检索多个 patterns 了。
  • -f: 可以将 patterns 放在一个文件中,每行是一个 pattern,然后用 -f 可以读取这个文件。还是上面这个例子,可以将 p1p2 放入 reg.txt 中,然后 grep -f reg.txt file 就行了,效果和上面使用两个 -e 完全一样。

常见参数

  • -r: 递归检索全部子路经下的全部文件,此时,最后的 <file> 是路径名。例如,grep -r 'test' /usr/local/。如果使用了 -r 但没有<file>,那么默认就是当前路径
  • -n: 在输出结果中增加行数(默认没有);
  • -w: 必须匹配整个 pattern。例如,如果要检索 ‘cat’,那么如果没有 -w,将会得到所有包含 ‘cat’ 的字符串(例如 cats 等),而加上该参数后就没有了;
  • -l: 只输出匹配的文件名(不输出内容);
  • -c: 输出的是统计出的每个文件中的 pattern 的个数;
  • -i: 忽略大小写;
  • -E: (注意是大写的 E) 将 pattern 看做加强版正则表达式(extended regular expression),它和普通的正则表达式的不同之处在于对某些特殊符号的处理方式上。参见下一章介绍。

一些特殊用法

只在某些特定文件类型中检索:

grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"

搜索时排除某些文件:

grep --exclude=*.o -rnw '/path/to/somewhere/' -e "pattern"

搜索时排除某些文件夹:

grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/somewhere/' -e "pattern"

举例:列出当前路径下全部的 .cpp 和 .hpp 文件

  • 方法 1:
    ls -l | grep '\.cpp\|\.hpp'
    
  • 方法2:使用方括号
    ls -l | grep '\.[ch]pp'
    

    or

    ls -l | grep '\.\(c\|h\)pp'
    
  • 方法3:使用 ERE 要简单一些,因为可以忽略上面的转义符
    ls -l | grep -E '\.cpp|\.hpp'`
    

或者用圆括号和“或”操作:

ls -l | grep -E '\.(c|h)pp'

几个注意:

  • 这里第一个转义符 \.是为了获取点 . 本身的含义。中间的转义符 \| 是为了得到 | 或操作符的特殊含义。
  • 注意 cpp 和 hpp 中间没有空格,因为如果有的话会默认把空格也当做一个待检索字符。

grep 和 find 的不同

从上面一章能看出,grep 和 ls 结合后也可以用来检索某个路径下的文件。那么,grep 和 find 的检索有何不同?其实,最主要的不同之处是,grep 是检索一个字符串,而 find 则是匹配字符串。前者是看是否存在,而后者则是要求匹配。注意两者的区别。

例如,为了找到当前目录下的 cpp 文件,可以用:

ls -l | grep '.cpp'

而用 find 的话就是:

find . -name '*.cpp'

即,find 中必须要用星号 *,因为它要找的文件名必须匹配上 *.cpp,如果不加星号,就变成了找一个文件名严格是 .cpp 的文件。而 grep 就不用,因为它只是在从当前目录的文件列表(这个字符串中)找 “.cpp” 这个子字符串,因此加上星号反倒是不对了。

复制文件路径

  • 在 Finder 下

    先按键 Cmd+i,然后从弹出的窗口里复制。

  • 在 Terminal 下

    pwd|pbcopy
    

线程/进程相关

查看文件被谁占用

使用 fuser 命令:

fuser -u .linux.md.swp

查看当前用户组的 ID

使用 id 命令,没有参数。

lsof: 查看打开的文件列表

An open file may be a regular file, a directory, a block special file, a character special file, an executing text reference, a library, a stream or a network file (Internet socket, NFS file or UNIX domain socket.) A specific file or all the files in a file system may be selected by path.

  • 查看网络相关的文件占用
lsof -i
  • 查看端口占用
lsof -i tcp:5037
  • 查看某个文件被谁占用
lsof .linux.md.swp
  • 查看某个用户占用的文件信息
lsof -u mazhuang

-u 后面可以跟 uid 或 login name。

  • 查看某个程序占用的文件信息
lsof -c Vim

注意程序名区分大小写。

修改文件(夹)的用户

有时候会有一些特殊文件(夹)的用户被默认设定成 root 而不是普通用户,此时可能会遇到类似 no permission 之类的警告或错误,例如某些 /.config/ 文件夹等。要修改用户,可以使用 chown 命令:

sudo chown -R $(whoami) <path>

这里 -R 是修改该路径下所有的子路径的权限(即 recursively),而不是仅仅是一个文件(夹);$(whoami) 默认就是你的用户名。

压缩文件

zip -r [output.zip] [folder]
zip [output.zip] [filename]

解压缩

tar xvjf *.tar.bz2 <-C some_directory>
tar xvzf *.tar.gz/tgz
tar xvf *.tar/.tar.xz
gunzip *.gz
unzip *.zip <-d some_directory>
bzip2 <-dk> *.bz2

In bzip2, the option -d is decompression, and -k is to keep original bz2 file (otherwise it will be deleted by default)

Ref: https://www.tecmint.com/linux-compress-decompress-bz2-files-using-bzip2/

显卡相关(Graphics Card)

Show existing graphics cards

sudo lshw -C video/display

Show existing graphics cards in the computer. Here video and display are equivalent.

Check the memory usage of Nvidia graphics card

nvidia-smi

Note it only works after you install nvidia driver successfully.

Search

    Table of Contents