文件系统

pwd

pwd命令显示列出当前所在的目录。

  1. $ pwd

cd

cd命令用来改变用户所在的目录。

  1. # 进入用户的主目录
  2. $ cd
  3. # 进入前一个工作目录
  4. $ cd -
  5. # 进入指定用户的主目录
  6. $ cd ~user_name

ls

ls目录可以显示指定目录的内容。不加参数时,显示当前目录的内容。

  1. $ ls

上面命令显示当前目录的内容。

ls命令也可以显示指定文件是否存在。

  1. $ ls foo.txt
  2. foo.txt

-l参数可以显示文件的详细信息。

  1. $ ls -l foo.txt
  2. -rw-rw-r-- 1 me me 0 2016-03-06 14:52 foo.txt

上面命令输出结果的第一栏,是文件的类型和权限。

文件类型分为以下几种。

  • - 普通文件
  • d 目录
  • l 符号链接。注意,对于符号链接文件,剩余的文件属性总是”rwxrwxrwx”。
  • c 字符设备文件,指按照字节流处理数据的设备,比如调制解调器。
  • b 块设备文件,指按照数据块处理数据的设备,比如硬盘。

其他参数的用法。

  1. # 显示多个目录的内容
  2. $ ls ~ /usr
  3. # -a --all 显示隐藏文件
  4. $ ls -a
  5. # -A 与-a类似,但是不显示当前目录和上一级目录两个点文件
  6. $ ls -A
  7. # -l 显示详细信息
  8. $ ls -l
  9. # -1 单列显示,每行只显示一个文件
  10. $ ls -1
  11. # -d 显示当前目录本身,而不是它的内容
  12. # 通常与-l配合使用,列出一个目录本身的详细信息
  13. $ ls -dl
  14. # -F 目录名之后添加斜杠,可执行文件后面添加星号
  15. $ ls -F
  16. # -h 与-l配合使用,将文件大小显示为人类可读的格式
  17. # -t 按文件修改时间排序,修改晚的排在前面
  18. $ ls -t
  19. # -s 按文件大小排序,
  20. # --reverse 显示结果倒序排列
  21. $ ls -lt --reverse

如果只显示一个目录里面的子目录,不显示文件,可以使用下面这些命令。

  1. # 只显示常规目录
  2. $ ls -d */
  3. $ ls -F | grep /
  4. $ ls -l | grep ^d
  5. $ tree -dL 1
  6. # 只显示隐藏目录
  7. $ ls -d .*/
  8. # 隐藏目录和非隐藏目录都显示
  9. $ find -maxdepth 1 -type d

另一个简便方法是利用自动补全功能,先键入cd命令,然后连按两下tab键。

stat

stat命令是加强版的ls命令,可以显示一个文件的详细信息。

  1. $ stat timestamp
  2. File: 'timestamp'
  3. Size: 0 Blocks: 0 IO Block: 4096 regular empty file
  4. Device: 803h/2051d Inode: 14265061 Links: 1
  5. Access: (0644/-rw-r--r--) Uid: ( 1001/ me) Gid: ( 1001/ me)
  6. Access: 2008-10-08 15:15:39.000000000 -0400
  7. Modify: 2008-10-08 15:15:39.000000000 -0400
  8. Change: 2008-10-08 15:15:39.000000000 -0400

touch

touch用来设置或更新文件的访问,更改,和修改时间。然而,如果一个文件名参数是一个 不存在的文件,则会创建一个空文件。

  1. $ touch timestamp

上面命令创建了一个名为timestamp空文件。如果该文件已经存在,就会把它的修改时间设置为当前时间。

  1. $ mkdir -p playground/dir-{00{1..9},0{10..99},100}
  2. $ touch playground/dir-{00{1..9},0{10..99},100}/file-{A..Z}

上面的命令创建了一个包含一百个子目录,每个子目录中包含了26个空文件。

file

file命令显示指定文件的类型。

  1. $ file picture.jpg
  2. picture.jpg: JPEG image data, JFIF standard 1.01

chmod

chmod命令用于更改文件的权限,是“change mode”的缩写。

  1. $ chmod 600 foo.txt

上面命令将foo.txt的权限改成了600。

chmod还可以接受四个缩写,为不同的对象单独设置权限。

  • u 所有者“user”的简写
  • g 用户组“group”的缩写
  • o 其他所有人“others”的简写
  • a 所有人“all”的简写
  1. # 为所有者添加可执行权限
  2. $ chmod u+x foo.txt
  3. # 删除所有者的可执行权限
  4. $ chmod u-x foo.txt
  5. # 为所有人添加可执行权限,等价于 a+x
  6. $ chmod +x foo.txt
  7. # 删除其他人的读权限和写权限。
  8. $ chmod o-rw foo.txt
  9. # 设定用户组和其他人的权限是读权限和写权限
  10. $ chmod go=rw foo.txt
  11. # 为所有者添加执行权限,设定用户组和其他人为读权限和写权限,多种设定用逗号分隔
  12. $ chmod u+x,go=rw foo.txt

添加权限。

  • +x 添加执行权限
  • +r 设置读权限
  • +w 设置写权限
  • +rwx 设置所有读、写和执行权限。

删除权限只需将+更改为-,就可以删除任何已设置的指定权限。可以使用-R(或--recursive)选项来递归地操作目录和文件。

设置精确权限,可以使用=代替+-来实现此操作。如果想为用户、组或其他用户设置不同的权限,可以使用逗号将不同表达式分开(例如ug=rwx,o=rx)。

由于一共有3种可能的权限。也可以使用八进制数代替符号来设置权限。通过这种方式设置的权限最多使用3个八进制数。第1个数定义用户权限,第2个数定义组权限,第3个数定义其他权限。这3个数中的每一个都通过添加想要的权限设置来构造:读 (4)、写 (2) 和执行 (1)。

  • rwx 7
  • rw- 6
  • r-x 5
  • r— 4
  • -wx 3
  • -w- 2
  • —x 1
  • —- 0

umask

umask用来查看和设置权限掩码。

  1. $ umask
  2. 0022

上面命令显示当前系统之中,默认的文件掩码是0022,转为二进制就是000 000 010 010

可以看到,这个掩码是一个12位的二进制数,后面的9位分别代表文件三种使用对象的三类权限。只要对应位置上是1,就表示关闭该项权限,所以010就表示关闭读权限。

新建文件时,通常不会带有执行权限,也就是说,新建文件的默认权限是rw-rw-rw-。如果文件掩码是0022,那么用户组和其他人的写权限也会被拿掉。

  1. $ touch new.txt
  2. $ ls -l new.txt
  3. -rw-r--r-- 1 me me 0 2016-03-06 14:52 new.txt

上面代码中,new.txt的用户组和其他人的写权限就没了。

umask后面跟着参数,就表示设置权限掩码。

  1. $ umask 0000

上面命令将权限掩码设为0000,实际上就是关闭了权限掩码。

umask命令设置的掩码值只能在当前Shell会话中生效,若当前Shell会话结束后,则必须重新设置。

du

du命令用于查看指定目录的大小。

  1. $ du -hs /path/to/directory

显示第一层子目录的大小。

  1. $ du -h --max-depth=1 /path/to/folder

参数的含义。

  • -h 表示人类可读的格式
  • -s 表示总结信息,否则会显示该目录内所有文件和子目录的信息。

tree命令也可以显示子目录大小。

  1. $ tree --du -h /path/to/directory

md5sum

md5sum命令用来显示一个文件的md5校验码。

  1. $ md5sum image.iso
  2. 34e354760f9bb7fbf85c96f6a3f94ece image.iso

locate

locate程序快速搜索本机的路径名数据库,并且输出每个与给定字符串相匹配的文件名。

  1. $ locate bin/zip
  2. /usr/bin/zip
  3. /usr/bin/zipcloak
  4. /usr/bin/zipgrep
  5. /usr/bin/zipinfo
  6. /usr/bin/zipnote
  7. /usr/bin/zipsplit

locate数据库由另一个叫做updatedb的程序创建。大多数装有 locate 的系统会每隔一天运行一回 updatedb 程序。因为数据库不能被持续地更新,所以当使用 locate 时,你会发现 目前最新的文件不会出现。为了克服这个问题,可以手动运行 updatedb 程序, 更改为超级用户身份,在提示符下运行 updatedb 命令。

locate支持正则查找。--regexp参数支持基本的正则表达式,--regex参数支持扩展的正则表达式。

  1. $ locate --regex 'bin/(bz|gz|zip)'

find

locate程序只能依据文件名来查找文件,而find程序能基于各种各样的属性,搜索一个给定目录(以及它的子目录),来查找文件。

  1. # 输出当前目录的所有子目录和文件(含子目录)
  2. $ find
  3. $ find .
  4. # 显示当前目录的文件总数
  5. $ find . | wc -l
  6. # 当前目录的子目录总数
  7. $ find . -type d | wc -l
  8. # 当前目录的文件总数(不含子目录)
  9. $ find . -type f | wc -l
  10. # 当前目录的文件名匹配“*.JPG”且大于1M的文件总数
  11. $ find . -type f -name "\*.JPG" -size +1M | wc -l

-type参数支持的文件类型。

  • b 块设备文件
  • c 字符设备文件
  • d 目录
  • f 普通文件
  • l 符号链接

-size参数支持的文件大小类型。

  • b 512 个字节块。如果没有指定单位,则这是默认值。
  • c 字节
  • w 两个字节的字
  • k 千字节
  • M 兆字节
  • G 千兆字节

find程序支持的查询参数。

  • -cmin n 匹配的文件和目录的内容或属性最后修改时间正好在 n 分钟之前。 指定少于 n 分钟之前,使用 -n,指定多于 n 分钟之前,使用 +n。
  • -cnewer file 匹配的文件和目录的内容或属性最后修改时间早于那些文件。
  • -ctime n 匹配的文件和目录的内容和属性最后修改时间在 n*24小时之前。
  • -empty 匹配空文件和目录。
  • -group name 匹配的文件和目录属于一个组。组可以用组名或组 ID 来表示。
  • -iname pattern 就像-name 测试条件,但是不区分大小写。
  • -inum n 匹配的文件的 inode 号是 n。这对于找到某个特殊 inode 的所有硬链接很有帮助。
  • -mmin n 匹配的文件或目录的内容被修改于 n 分钟之前。
  • -mtime n 匹配的文件或目录的内容被修改于 n*24小时之前。
  • -name pattern 用指定的通配符模式匹配的文件和目录。
  • -newer file 匹配的文件和目录的内容早于指定的文件。当编写 shell 脚本,做文件备份时,非常有帮助。 每次你制作一个备份,更新文件(比如说日志),然后使用 find 命令来决定自从上次更新,哪一个文件已经更改了。
  • -nouser 匹配的文件和目录不属于一个有效用户。这可以用来查找 属于删除帐户的文件或监测攻击行为。
  • -nogroup 匹配的文件和目录不属于一个有效的组。
  • -perm mode 匹配的文件和目录的权限已经设置为指定的 mode。mode 可以用 八进制或符号表示法。
  • -samefile name 相似于-inum 测试条件。匹配和文件 name 享有同样 inode 号的文件。
  • -size n 匹配的文件大小为 n。
  • -type c 匹配的文件类型是 c。
  • -user name 匹配的文件或目录属于某个用户。这个用户可以通过用户名或用户 ID 来表示。
  • -depth 指导 find 程序先处理目录中的文件,再处理目录自身。当指定-delete 行为时,会自动 应用这个选项。
  • -maxdepth levels 当执行测试条件和行为的时候,设置 find 程序陷入目录树的最大级别数
  • -mindepth levels 在应用测试条件和行为之前,设置 find 程序陷入目录数的最小级别数。
  • -mount 指导 find 程序不要搜索挂载到其它文件系统上的目录。
  • -regex 指定正则表达式
  1. # 找出包括空格或其它不规范字符的文件名或路径名
  2. $ find . -regex '.*[^-\_./0-9a-zA-Z].*'

find程序还支持逻辑操作符。

  • -and 如果操作符两边的测试条件都是真,则匹配。可以简写为 -a。 注意若没有使用操作符,则默认使用 -and。
  • -or 若操作符两边的任一个测试条件为真,则匹配。可以简写为 -o。
  • -not 若操作符后面的测试条件是真,则匹配。可以简写为一个感叹号(!)。
  • () 把测试条件和操作符组合起来形成更大的表达式。这用来控制逻辑计算的优先级。注意 因为圆括号字符对于 shell 来说有特殊含义,所以在命令行中使用它们的时候,它们必须 用引号引起来,才能作为实参传递给 find 命令。通常反斜杠字符被用来转义圆括号字符。
  1. # 或关系
  2. ( expression 1 ) -or ( expression 2 )
  3. # 找出不是600权限的文件,或者不是700权限的目录
  4. $ find ~ \( -type f -not -perm 0600 \) -or \( -type d -not -perm 0700 \)

find程序的逻辑表达式,具有“短路运算”的特点,即对于expr1 -operator expr2这个表达式,expr2不一定执行。这是为了提高运行速度。

  • expr1 为真,且操作符为-and,expr2 总是执行
  • expr1 为假,且操作符为-and,expr2 从不执行
  • expr1 为真,且操作符为-or,expr2 从不执行
  • expr1 为假,且操作符为-or,expr2 总是执行

为了方便执行一些常见操作,find程序定义了一些预定义操作。

  • -delete 删除当前匹配的文件。
  • -ls 对匹配的文件执行等同的 ls -dils 命令。并将结果发送到标准输出。
  • -print 把匹配文件的全路径名输送到标准输出。如果没有指定其它操作,这是 默认操作。
  • -quit 一旦找到一个匹配,退出。
  1. # 找到匹配的文件,并显示在标准输出
  2. # -print 是默认操作,可以省略
  3. $ find . -print
  4. # 删除后缀名为BAK的文件
  5. # 执行 delete 操作前,最好先执行 print 操作,确认要删除哪些文件
  6. $ find . -type f -name '*.BAK' -delete

预定义操作可以与逻辑表达式,结合使用。

  1. $ find ~ -type f -and -name '*.BAK' -and -print

除了预定义操作以外,用户还可以使用-exec参数自定义操作。

  1. -exec command {} ;

上面的命令中,command是一个命令行命令,{}用来指代当前路径,分号表示命令结束。

  1. # 预定义的 -delete 操作,等同于下面的操作
  2. -exec rm '{}' ';'

-exec使用时,每次找到一个匹配的文件,会启动一个新的指定命令的实例。

  1. $ find ~ -type f -name 'foo*' -exec ls -l '{}' ';'

执行上面的命令,ls程序可能会被调用多次。

  1. $ ls -l file1
  2. $ ls -l file2

如果想改成ls程序只调用一次,要把find命令里面的分号,改成加号。

  1. $ ls -l file1 file2
  2. # 相当于
  3. $ find ~ -type f -name 'foo*' -exec ls -l '{}' +

xargs

xargs命令从标准输入接受输入,并把输入转换为一个特定命令的参数列表。

  1. $ find ~ -type f -name 'foo\*' -print | xargs ls -l