本文是学习Linux命令 (Learn linux command)系列文章的第三篇,在这里会介绍一些让大家平时都会经常用到的命令。注意,命令出现的顺序与重要程度无关。
1. ls - list directory contents
ls命令是用得比较多的一个命令,它用于列出某个目录下面的文件或者子目录及它们的属性(大小、创建时间、所属用户等信息)。
ls命令的参数比较多,这里只介绍一些实用的。
a. 通过-a选项列出目录下面的隐藏文件(即以.号开头的文件),例如:
# ls -a ~ . .. .bash_history .bash_logout .bash_profile .bashrc .cshrc .tcshrc .viminfo
其中.和..表示当前目录与上一级目录,如果不想显示可以使用-A选项。
# ls -A ~ .bash_history .bash_logout .bash_profile .bashrc .cshrc .tcshrc .viminfo
b. 通过-l选项列出文件的详细信息,例如:
# ls -l /boot total 19256 -rw-r--r--. 1 root root 101820 Jun 22 2012 config-2.6.32-279.el6.x86_64 drwxr-xr-x. 3 root root 4096 Dec 17 09:08 efi drwxr-xr-x. 2 root root 4096 Dec 17 09:09 grub -rw-r--r--. 1 root root 13057907 Dec 17 09:09 initramfs-2.6.32-279.el6.x86_64.img -rw-r--r--. 1 root root 179157 Jun 22 2012 symvers-2.6.32-279.el6.x86_64.gz -rw-r--r--. 1 root root 2341856 Jun 22 2012 System.map-2.6.32-279.el6.x86_64 -rwxr-xr-x. 1 root root 3986608 Jun 22 2012 vmlinuz-2.6.32-279.el6.x86_64
上面结果中的每一列的说明可以参考info ls:
print the file type, file mode bits, number of hard links, owner name, group name, size, and
timestamp (*note Formatting file timestamps::), normally the modification time.
参考手册我们一一来说明各个列分别对应的是:
- 第一列表示文件的类型,其中'-'表示普通文件,'d'表示目录,'b'表示块设备文件,'c'表示字符设备文件,'l'表示符号链接,'p'表示管道文件, 's'表示socket文件等等;
- 第二列是文件的权限位;
- 第三列是硬链接的个数;
- 第四、五列分别是文件所属的用户和用户组;
- 第六列是指文件大小;
- 第七列是文件的修改时间;
- 第八列是文件的名称;
如果加上-i选项还可以列出文件的inode号,inode号将会显示在第一列。
c. 指定-d选项仅列出目录,而不是目录的内容。
有时候我们要列出一个目录的属性,但是不是列出目录的内容,如果我们使用ls -l /etc/会列出/etc/目录下的所有内容,这个时候就需要使用-d选项限制:
# ls -ld /etc drwxr-xr-x. 59 root root 4096 Mar 4 16:40 /etc
d. 指定-h列出可读性高的结果,将大小转换成如1k, 200M, 3G等形式,例如:
# ls -lh /boot/ total 19M -rw-r--r--. 1 root root 100K Jun 22 2012 config-2.6.32-279.el6.x86_64 drwxr-xr-x. 3 root root 4.0K Dec 17 09:08 efi drwxr-xr-x. 2 root root 4.0K Dec 17 09:09 grub -rw-r--r--. 1 root root 13M Dec 17 09:09 initramfs-2.6.32-279.el6.x86_64.img -rw-r--r--. 1 root root 175K Jun 22 2012 symvers-2.6.32-279.el6.x86_64.gz -rw-r--r--. 1 root root 2.3M Jun 22 2012 System.map-2.6.32-279.el6.x86_64 -rwxr-xr-x. 1 root root 3.9M Jun 22 2012 vmlinuz-2.6.32-279.el6.x86_64
--si选项类似-h,只不过--si假设1kb=1000b,而不是1024。
e. 使用--sort选项排序列出的文件,例如:
默认情况下是按照文件名排序,我们可以换成其它排序方式,例如按照时间排序:
# ls -l --sort=time /boot/ total 19256 drwxr-xr-x. 2 root root 4096 Dec 17 09:09 grub -rw-r--r--. 1 root root 13057907 Dec 17 09:09 initramfs-2.6.32-279.el6.x86_64.img drwxr-xr-x. 3 root root 4096 Dec 17 09:08 efi -rw-r--r--. 1 root root 179157 Jun 22 2012 symvers-2.6.32-279.el6.x86_64.gz -rw-r--r--. 1 root root 101820 Jun 22 2012 config-2.6.32-279.el6.x86_64 -rw-r--r--. 1 root root 2341856 Jun 22 2012 System.map-2.6.32-279.el6.x86_64 -rwxr-xr-x. 1 root root 3986608 Jun 22 2012 vmlinuz-2.6.32-279.el6.x86_64
--sort选项的值可以为none(按照inode号排序),size(文件大小排序),time(修改时间排序)等等。其中--sort=time相当于-t。
通过-r选项可以逆序排序,所以我们经常看到这样用:ls -ltr,表明按照修改时间逆序排序文件。
f. 使用-1(数字1)选项列出文件,一行一个文件,这个大多数用于脚本中。
2. touch - change file timestamps
touch命令可以用于创建空文件,这是我们平时使用最多的一点,而且它还可以用来更改文件的修改时间(mtime:文件内容最近修改的时间)和访问时间(atime:文件内容最近打开读的时间),同时将文件的改变时间(ctime:文件属性最近改变的时间)更新为当前时间。文件内容的修改也会更新ctime的时间。
例如当前目录有一个文件1.txt,当前它的atime/ctime/mtime如下所示:
# stat 1.txt File: `1.txt' Size: 4 Blocks: 8 IO Block: 4096 regular file Device: ca01h/51713d Inode: 270217 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2013-03-06 12:21:50.526594045 +0800 Modify: 2013-03-06 12:21:38.098237950 +0800 Change: 2013-03-06 12:21:58.866833152 +0800
现在我们执行touch 1.txt
命令,它默认会更新所有的时间为当前时间:
# touch 1.txt # stat 1.txt File: `1.txt' Size: 4 Blocks: 8 IO Block: 4096 regular file Device: ca01h/51713d Inode: 270217 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2013-03-06 12:23:20.909178823 +0800 Modify: 2013-03-06 12:23:20.909178823 +0800 Change: 2013-03-06 12:23:20.909178823 +0800
我们可以通过添加-m或者-a选项仅修改mtime或者atime(记住ctime是一定会变化的):
# touch -m 1.txt # stat 1.txt File: `1.txt' Size: 4 Blocks: 8 IO Block: 4096 regular file Device: ca01h/51713d Inode: 270217 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2013-03-06 12:23:20.909178823 +0800 Modify: 2013-03-06 12:24:40.891474834 +0800 Change: 2013-03-06 12:24:40.891474834 +0800
那如果想要设置成其它时间,可以通过-d或者-t参数指定,其中-d指定的格式比较智能,但是也不容易指定。比较推荐使用-t选项,它的值格式为[[CC]YY]MMDDhhmm[.ss]
,例如197001010000.00:
# touch -t 197001010000.00 -a 1.txt # stat 1.txt File: `1.txt' Size: 4 Blocks: 8 IO Block: 4096 regular file Device: ca01h/51713d Inode: 270217 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 1970-01-01 00:00:00.000000000 +0800 Modify: 2013-03-05 11:00:00.000000000 +0800 Change: 2013-03-06 12:37:52.142045891 +0800 Birth: -
参考资料:
- http://www.linfo.org/touch.html
- http://linux.about.com/library/cmd/blcmdl_touch.htm
3. du - estimate file space usage
du命令可以用于统计文件或者目录的大小,大多数情况下,这个命令可以用于监控某个目录的大小是否超过某个警界值。
例如:
$ date > 1.txt $ du 1.txt 4 1.txt
上面的结果表示1.txt这个文件有4KB,如果我们用ls -l命令查看结果却不一样:
$ ls -l 1.txt -rw-r--r-- 1 kodango kodango 29 Mar 9 12:52 1.txt
可见,实际的大小只有29byte,这也实际的大小是一致的。那为什么du和ls命令的结果有这样的区别呢,原因是ls命令默认显示的是文件的实际大小,而du命令是显示文件在物理硬盘上占用的大小,因为文件分配的最小单位是block,可以通过tune2fs命令查看文件系统的block size:
$ sudo tune2fs -l /dev/sda1 | grep 'Block size' Block size: 4096
默认刚好是4K,所以du的命令结果就可以解释了。du命令也提供--apparent-size来显示文件的实际大小:
du --apparent-size -h 1.txt 29 1.txt
这里的-h选项与ls的-h一样,将大小转换成如1k, 200M, 3G等形式,这样便于阅读,-h的进制是1024,如果要使用1000作为进制,可以使用--si选项,很多系统上都标明-h选项已经过时。
不指定参数的情况下du会计算当前目录下的子目录的大小,通过-a选项可以计算包括文件在内的所有大小,例如:
[kodango@devops temp]$ du -ah 4.0K ./sub/3.txt 8.0K ./sub 4.0K ./1.txt 8.0K ./2.txt 24K .
4. df - report file system disk space usage
df命令用来显示文件系统的空间使用情况,因为针对的是文件系统,我们可以利用该命令很清晰地看出当前系统分区挂载的情况。一般情况下,我会通过-hT参数来显示:
$ df -hT Filesystem Type Size Used Avail Use% Mounted on /dev/sda3 ext3 142G 133G 2.6G 99% / /dev/sda1 ext3 487M 116M 346M 25% /boot tmpfs tmpfs 12G 52K 12G 1% /dev/shm
其中,-h将大小转换成易读的单位,例如M, G等,-T则是同时显示文件系统类型。
5. split - split a file into pieces
将一个大文件分割成多个小文件,这应该是一个比较常见的需求。有了split命令,分割文件的操作就很简单了,你根本不需要花心思再找工具甚至写代码来完成这个任务。
split命令将文件分割成PREFIXaa, PREFIXab, ...等多个小文件,默认情况下PREFIX为x,当然你也可以自己指定。这个命令的用法比较简单,下面是几个例子。
1) 以每个文件500行分割
$ split -l 500 messages $ wc -l x* 500 xaa 500 xab 500 xac 242 xad 1742 total
2) 以每个文件50K分割
$ split -b 50k messages $ wc -c x* 51200 xaa 51200 xab 44612 xac 147012 total
3) 指定前缀及数字后缀分割
$ split -b 50k -d messages msg wc -c msg* 51200 msg00 51200 msg01 44612 msg02 147012 total
6. md5sum - compute and check MD5 message digest
md5sum用于计算和检验文件的md5值,通过md5值我们可以唯一确定某个文件,从而验证文件的合法性,避免文件损坏。
md5sum有两种读入模式:binary和text,但是在Linux上这两者基本上没有什么区别,只不过输出时影响文件的标志位。如果是binary模式,在输出结果中文件名前面显示*;如果是text模式,则在输出结果中文件名前面显示空格,例如:
$ md5sum -b /bin/bash e764fe17b0b5043e83838352e958f77d */bin/bash $ md5sum /bin/bash e764fe17b0b5043e83838352e958f77d /bin/bash
注意第二个结果中,中间有两个空格,前面一个是用于分隔md5值与文件名,后一个空格是标志模式。
md5sum的另外一个作用是检验文件是否准确,在一些iso或者大型文件下载站,往往会给出文件对应的md5sums.txt,例如:
$ cat md5sums.txt 63bb5b8b78b02cdc75fc23222b09c46a messages $ md5sum -c md5sums.txt messages: OK
这个时候,可以通过-c参数来检验文件,md5sums.txt的格式与之前用md5sum命令计算文件的md5值的输出格式是一样的。所以千万不要画龙点睛,把中间的两个空格写成一个空格哦。
7. uniq - report or omit repeated lines
uniq命令顾名思义就是用来处理重复行的,如果仅仅是删除重复行,我们在上一节中介绍的sort命令出可以完成这个任务(sort -u)。但是,uniq是专门用于处理重复行的,它的功能更加丰富点。
uniq处理的文件必须是已经排好序的(可以使用sort排序文件)。
我们用以下一个排好序的简单文件来解释uniq的用法:
$ cat ip.list 10.0.0.1 10.0.0.2 10.0.0.2 10.0.0.3
1)删除重复行
$ uniq ip.list 10.0.0.1 10.0.0.2 10.0.0.3
2) 统计相同行出现的次数
$ uniq -c ip.list 1 10.0.0.1 2 10.0.0.2 1 10.0.0.3
3) 仅显示重复的行
$ uniq -d ip.list 10.0.0.2
4) 仅显示不重复的行
$ uniq -u ip.list 10.0.0.1 10.0.0.3
8. tr - translate or delete characters
tr是translate翻译的意思,它可以将一个集合内的字符(SET1)转换成另外一个集合内的字符(SET2)。当然,除这个最基本的功能外,它还有诸如删除、压缩等功能。
一个最常用的tr用法是将小写字母转换成大写字母:
$ echo "hello, world" | tr a-z A-Z HELLO, WORLD
这里SET1是a-z,SET2是A-Z。a-z是tr支持的特殊序列,表示从a到z的所有小写字母,了解正则的同学可能会比较容易理解,因为同[a-z]的功能是一样的。
tr支持很多种序列的表示,具体可以看man的手册,这里再例举两个。
1) [CHAR*]与[CHAR*REPEAT]
这两种表示法只能用于SET2,前者是说SET2的字符全是CHAR,将SET1中的字符全部替换成CHAR;后者的意思是说CHAR字符重复REPEAT次,SET1中的前REPEAT个字符替换成CHAR。
举两个例子来说明:
$ echo '123456789' | tr 1-5 '[x*]' # 1-5全部替换成x xxxxx6789 $ echo '123456789' | tr 1-5 '[x*3]yz' # 1-3替换成x,4-5替换成y-z xxxyz6789
2) \NNN
\NNN是用1-3位的八进制数来表示字符,例如\101表示大写字母A:
$ echo '123456789' | tr 1-3 '\101-\103' ABC456789
tr命令支持的参数不多,就以下几个,每个参数对应不同的操作:
$ tr --help Usage: tr [OPTION]... SET1 [SET2] Translate, squeeze, and/or delete characters from standard input, writing to standard output. -c, -C, --complement first complement SET1 -d, --delete delete characters in SET1, do not translate -s, --squeeze-repeats replace each input sequence of a repeated character that is listed in SET1 with a single occurrence of that character -t, --truncate-set1 first truncate SET1 to length of SET2
其中:
- -c:对SET1中的内容求补集,例如-c 1+-表示除1+-外的所有字符;
- -d:删除出现在SET1中的字符,而不是翻译转换;
- -s:将连续的并且出现在SET1中的字符压缩为一个;
- -t:将SET1集合的长度裁成与SET2集合的长度相同,即SET1中末尾多余的字符会被忽略;
下面拿几个例子来解释以上的参数:
1) -c SET1
将除1-3和回车之外的所有字符替换成4(SET2仅能为单个字符?):
$ echo '123456789' | tr -c '1-3\n' 4 123444444
2) -d SET1
将1-3三个字符从字符串中删除:
$ echo '123456789' | tr -d '1-3' 456789
-d如果与-c参数一起使用,意思是指删除SET1出现的字符以外的其它字符:
$ echo '123456789' | tr -dc '1-3\n' 123
3) -s SET1
如果SET1中的字符,在字符串中连续现出,则压缩成1个:
$ echo '11233' | tr -s 1 1233
-s选项可以用于-d或者翻译转换的场景,但是在这两个情况下-s只压缩出现在SET2中的字符,例如
$ echo '11233' | tr -s 1-3 2-4 # 等价于 tr 1-3 2-4 && tr -s 2-4 234
4) -t SET1 SET2
这里的t是truncate的意思,如果SET1的长度比SET2大,则忽略SET1中多余的字符,例如:
$ echo '12345' | tr -t 1-5 2-4 23445
在这里仅替换了1、2、3三个字符,4-5则被忽略了。
9. mv - move (rename) files
mv是平时使用得比较多的一个命令,它用于移动文件或者目录,也可以说是对文件或者目录做重命名。但是一个简单的命令也有一些我们平时没有留意的地方。
1)如果目标文件或者目录存在怎么办,能不能先备份它?
$ touch source dst $ mv -b source dst $ ls dst* -1 dst dst~
-b选项就是backup的意思,如果目标存在,则先备份。
2)如果仅仅要移动更新过的文件,能不能做到?
mv命令有一个-u选项,它仅仅当源文件比目标文件更新,或者目标文件不存在是才移动,例如
$ date > source $ cp source source.bak $ ls -lh source source.bak -rw-r--r-- 1 admin admin 29 May 2 14:50 source -rw-r--r-- 1 admin admin 29 May 2 14:50 source.bak $ mv -u source source.bak $ ls -lh source source.bak -rw-r--r-- 1 admin admin 29 May 2 14:50 source -rw-r--r-- 1 admin admin 29 May 2 14:50 source.bak $ date > source $ mv -u source source.bak $ ls -lh source source.bak ls: source: No such file or directory -rw-r--r-- 1 admin admin 29 May 2 14:51 source.bak