鸟哥的Linux私房菜第六章学习笔记

第6章 Linux文件与目录管理

一、要点总结

6.1 目录与路径

6.1.1 相对路径和绝对路径

  • 绝对路径:由根目录/写起。一般正确度更好。
  • 相对路径:不由根目录写起。有利于程序安装在不同的目录之下。

6.1.2 目录相关操作

  • 特殊的目录

    • .:代表此层目录
    • ..:代表上一层目录
    • -:代表到达过的上一个工作目录
    • ~:代表目前使用者的家目录
    • ~account:代表account用户的家目录
  • 常见的处理目录的命令

    • cd:切换目录 Change Directory

      1
      2
      cd [相对路径、绝对路径或特殊目录] # 切换到特定目录
      cd # 单独的cd代表回到使用者家目录
    • pwd:显示当前工作目录 Print Working Directory

      1
      2
      3
      pwd [-R]
      # 选项与参数:
      # -P : 显示出真正的路径,而非使用链接(link)路径。
    • mkdir:建立一个新目录 Make Directory

      1
      2
      3
      4
      mkdir [-mp] 目录名称
      # 选项与参数:
      # -m : 直接设置文件的权限,后跟权限值,不适用默认的umask权限
      # -p : 递归创建需要的目录(默认情况下是需要一层一层建立的)。
    • rmdir:删除一个空目录

      • 空目录指的是里面不存在其他目录或文件的目录
      1
      2
      3
      rmdir [-p] 目录名称
      # 选项与参数:
      # -p : 递归删除上层的空目录
      • 非空目录的删除可以使用rm -r 目录名称

6.1.3 关于执行文件路径的变量:$PATH

  • 用户能使用的命令是根据PATH变量所规定的目录去查找。

    • 系统会依照PATH的设置去每个PATH里的目录下查找对应的可执行文件,如果有多个同名,那么先查找到的同名命令先被执行,因此通过路径指定可执行文件会比通过PATH来执行来得正确。
  • 不同身份用户默认的PATH不同,默认能随意执行的命令也不同(如root和dmtsai)。

    1
    echo $PATH

    输入上述命令后可以看到当前用户的PATH。它由一堆目录组成,每个目录中间用冒号(:)隔开。

  • PATH是可以被修改的,可以直接通过衔接字符串的方法增加:

    1
    PATH="${PATH}:/root"
    • 但是为了安全起见,不建议将本目录(.)加入PATH的查找目录

6.2 文件 与目录管理

6.2.1 文件与目录的查看:ls

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ls [-aAdfFhilnrRSt] 文件名或目录名称
ls [--color={never,auto,always}] 文件名或目录名称
ls [--full-time] 文件名或目录名称
# 选项与参数:
# -a :全部的文件,连同隐藏文件(开头为.的文件)一起列出来(常用)
# -A :全部的文件,连同隐藏文件,但不包括.与..这两个目录
# -d :仅列出目录本身,而不是列出目录内的文件数据(常用)
# -f :直接列出结果,而不进行排序(ls默认会以文件名排序)
# -F :根据文件、目录等信息,给予附加数据结构,例如:
# *:代表可可执行文件;/:代表目录;=:代表socket文件;|:代表 FIFO 文件
# -h :将文件大小以人类较易读的方式(例如GB,KB等等)列出来
# -i :列出inode号码
# -l :详细信息显示,包含文件的属性与权限等等数据(常用)
# -n :列出UID与GID而非使用者与用户组的名称
# -r :将排序结果反向输出
# -R :连同子目录内容一起列出来,等于该目录下的所有文件都会显示出来
# -S :以文件大小大小排序,而不是用文件名排序
# -t :依时间排序,而不是用文件名
# --color=never :不要依据文件特性给予颜色显示
# --color=always :显示颜色
# --color=auto :让系统自行依据设置来判断是否给予颜色
# --full-time :以完整时间模式(包含年、月、日、时、分)输出
# --time={atime,ctime} :输出access时间或改变权限属性时间(ctime)
# 而非内容变更时间(modification time)
  • 只执行ls默认是显示着色的非隐藏文件的文件名、以文件名进行排序。
  • 很多Linux发行版在默认情况下,已经将ll通过alias设置成ls -l的意思。

6.2.2 复制、删除和移动:cp、rm、mv

cp(复制文件或目录)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cp [-adfilprsu] source destination
cp [options] source1 source2 source3 .... directory
# 选项与参数:
# -a :相当于-dr --preserve=all(常用)
# -d :若source为链接文件的属性(link file),则复制链接文件属性而非文件本身
# -f :为强制(force)的意思,若目标文件已经存在且无法打开,则删除后再尝试一次
# -i :若destination已经存在时,在覆盖时会先询问操作的进行(常用)
# -l :进行硬链接(hard link)的链接文件创建,而非复制文件本身
# -p :连同文件的属性(权限、用户、时间)一起复制过去,而非使用默认属性(备份常用)
# -r :递归复制,用于目录的复制行为(常用)
# -s :复制成符号链接文件(symbolic link),亦即“快捷方式”文件
# -u :source比destination新才更新destination,或destination不存在的情况下才复制
# --preserve=all :除了-p的权限相关参数外,还加入SELinux的属性,links、xattr等也复制
# 最后需要注意的,如果源文件有两个以上,则最后一个目的文件一定要是“目录”才行!
  • 默认情况下,cp的源文件和目标文件的权限是不同的,目标文件的拥有者会变成命令操作者本身。文件建立的时间也会发生变化。
    • 由于普通用户并不能随意修改文件的拥有者和用户组,即使加上-a属性,也无法完成目标文件拥有者和用户组的复制
  • 没有加上任何选项时,cp一个链接文件复制的是原始文件,而不是链接文件的属性。如果要复制链接文件的属性,就要加上-d了。

rm(删除文件或目录)

1
2
3
4
5
rm [-fir] 文件或目录
# 选项与参数:
# -f :就是force的意思,忽略不存在的文件,不会出现警告讯息;
# -i :交互模式,在删除前会询问使用者是否操作
# -r :递归删除,最常用于目录的删除,这是非常危险的选项。
  • 如果身份是root,默认把rm -r通过alias替换成了rm -ri,作为对系统的保护。可以通过在命令前加反斜杠\rm -r来忽略掉alias的指定选项。

mv(移动文件或目录,或重命名)

1
2
3
4
5
6
mv [-fiu] source destination
mv [options] source1 source2 source3 .... directory
# 选项与参数:
# -f :force强制的意思,如果destination已经存在,不会询问而直接覆盖
# -i :若destination已经存在,就会询问是否覆盖
# -u :若destination已经存在,且source比较新,才会更新(update)
  • mv还可用于修改文件名,不过Linux还有rename命令专门用来更改大量文件的文件名

6.2.3 获取路径的文件名与目录名称

1
2
3
4
basename /etc/sysconfig/network # 取得最后的文件名
# 输出network
dirname /etc/sysconfig/network # 取得目录名称
# 输出/etc/sysconfig

6.3 文件内容查看

  • cat由第一行开始显示文件内容,tac从最后一行开始显示
  • nl显示的时候同时输出行数
  • more一页一页显示文件内容。lessmore类似但是可以往前翻页。
  • head只看前几行,tail只看后几行
  • od以二进制的方式读取文件内容

6.3.1 直接查看文件内容

cat(Concatenate)

1
2
3
4
5
6
7
8
cat [-AbEnTv] 文件名
# 选项与参数:
# -A :相当于-vET的整合选项,可列出一些特殊字符而不是空白而已
# -b :列出行号,仅针对非空白行做行号显示,空白行不标行号
# -E :将结尾的断行字符$显示出来
# -n :打印出行号,连同空白行也会有行号,与 -b 的选项不同
# -T :将 [tab] 按键以^I显示出来
# -v :列出一些看不出来的特殊字符

tac(反向列示)

  • 由最后一行到第一行反向在屏幕上显示出来
1
tac 文件名

nl(添加行号打印)

1
2
3
4
5
6
7
8
9
10
nl [-bnw] 文件
# 选项与参数:
# -b :指定行号指定的方式,主要有两种:
# -b a :表示不论是否为空行,也同样列出行号(类似cat -n);
# -b t :如果有空行,空的那一行不要列出行号(默认);
# -n :列出行号表示的方法,主要有三种:
# -n ln :行号在屏幕的最左方显示;
# -n rn :行号在自己字段的最右方显示,且不加 0 ;
# -n rz :行号在自己字段的最右方显示,且加 0 ;
# -w :行号字段的占用的字符数。

6.3.2 可翻页查看

more(一页一页翻动)

有几个按键可以按的:

  • 空格键(space):代表下翻一页
  • Enter:下翻一行
  • /字符串:代表在这个显示的内容中,向下查找字符串这个关键词
    • 按n查找下一个匹配的字符串
  • :f:立刻显示出文件名以及目前显示的行数
  • q:代表立刻离开more ,不再显示该文件内容
  • b或[ctrl]-b:代表往回翻页,不过这动作只对文件有用,对管线无用

less(一页一页翻动,增加往上翻动)

相较于more,less可以向上向下翻动和查找,方便了很多。可以使用的指令有:

  • 空格键:向下翻动一页
  • [pagedown]:向下翻动一页
  • [pageup]:向上翻动一页
  • /字符串:向下查找字符串
  • ?字符串:向上查找字符串
  • n:重复前一个查找(与/或?有关)
  • N:反向重复前一个查找
  • g:前进到这个数据的第一行
  • G:前进到这个数据的最后一行
  • q:离开less这个程序

这些按键实际上在介绍man时介绍过了,因为man就是调用less来显示文件内容的。

6.3.3 数据截取

head(取出前几行)

1
2
3
head [-n number] 文件
# 选项与参数:
# -n :后面接数字,代表显示几行的意思。
  • 缺省情况下显示前10行。
  • number可以是个负数,代表打印倒数第number行前的所有行

tail(取出后几行)

1
2
3
4
tail [-n number] 文件
# 选项与参数:
# -n :后面接数字,代表显示几行的意思
# -f :表示持续刷新后面所接的文件中的内容,要等到按下[ctrl]-c才会结束
  • 缺省情况下显示后10行。
  • number前可以加上+,表示打印正数number行后的所有内容

6.3.4 非纯文本文件:od

1
2
3
4
5
6
7
8
9
od [-t TYPE] 文件
# 选项或参数:
# -t :后面可以接各种“类型 (TYPE)”的输出,例如:
# a :利用默认的字符来输出;
# c :使用 ASCII 字符来输出
# d[size] :利用十进制(decimal)来输出数据,每个整数占用 size Bytes
# f[size] :利用浮点数值(floating)来输出数据,每个数占用 size Bytes
# o[size] :利用八进位(octal)来输出数据,每个整数占用 size Bytes
# x[size] :利用十六进制(hexadecimal)来输出数据,每个整数占用 size Bytes

6.3.5 修改文件时间或创建新文件:touch

Linux下文件有三个主要的变动时间,这三个时间的意义是:

  • 修改时间(modification time,mtime):文件内容数据变动的时间
  • 状态时间(status time,ctime):文件的状态,如权限或属性,变动的时间
  • 读取时间(access time,atime):文件内容被读取的时间

在默认情况下,ls显示出来的是该文件的mtime。想让文件的时间变成【现在】的时间,就需要借助touch命令

1
2
3
4
5
6
7
touch [-acdmt] 文件
# 选项与参数:
# -a :仅修订 access time;
# -c :仅修改文件的时间,若该文件不存在则不创建新文件;
# -d :后面可以接欲自定义的日期而不用目前的日期,也可以使用 --date="日期或时间"
# -m :仅修改 mtime ;
# -t :后面可以接欲自定义的时间而不用目前的时间,格式为[YYYYMMDDhhmm]
  • 本质上,touch改变的只有mtime和atime,ctime是系统自动管理的。
  • 默认情况下,touch一个文件会让这个文件的三个时间都变成现在。若这个文件不存在会被新建成一个空文件,因此touch也被用于新建空文件。

6.4 文件与目录的默认权限与隐藏权限

6.4.1 文件默认权限:umask

在默认情况下,若用户建立为文件则默认没有可执行(x)权限,即只有rw这两个项目,最大为666:-rw-rw-rw-。若用户建立为目录,则由于x与是否可以进入这个目录有关,因此默认所有权限都是开放的,即777:drwxrwxrwx。

umask就用于查看或修改用户建立文件或目录的默认权限。查看有两种方法

1
2
3
4
umask # 打印数字类型的权限值
# 0022
umask -S # 打印符号类型的权限
# u=rwx,g=rx,o=rx

umask返回的数字指的是上面默认值需要减掉的权限。比如022的umask指的就是新建的文件或目录的权限里,相较于默认权限,需要在group和others两个维度去掉w这个权限。

设置umask直接通过umask 数字即可,如umask 002

在默认情况下,root的umask会因为安全原因拿掉比较多的属性,默认是022。而一般身份的用户的umask是002,保留了同组用户的写入能力。

6.4.2 文件隐藏属性

除了rwx属性,文件还有一些隐藏属性。这些隐藏属性对于系统有很大的帮助,尤其是在系统安全上面。不过要先强调的是,下面的chattr指令只能在Ext2/Ext3/Ext4的Linux传统文件系统上面完整生效, 其他的文件系统如xfs可能就无法完整的支持这个指令了。

chattr(配置文件隐藏属性)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
chattr [+-=][ASacdistu] 文件或目录名称
# 选项与参数:
# + :增加某一个特殊参数,其他原本存在参数则不动。
# - :移除某一个特殊参数,其他原本存在参数则不动。
# = :设置一定,且仅有后面接的参数
#
# A :当设置了A这个属性时,若你有存取此文件(或目录)时,他的存取时间atime将不会被修改,
# 可避免I/O较慢的机器过度的存取磁盘。(目前建议使用文件系统挂载参数处理这个项目)
# S :一般文件是非同步写入磁盘的(原理请参考前一章sync的说明),如果加上S这个属性时,
# 当你进行任何文件的修改,该更动会【同步】写入磁盘中。
# a :当设置a之后,这个文件将只能增加数据,而不能删除也不能修改数据,只有root才能设置这属性
# c :这个属性设置之后,将会自动的将此文件【压缩】,在读取的时候将会自动解压缩,
# 但是在储存的时候,将会先进行压缩后再储存(看来对于大文件似乎蛮有用的!)
# d :当dump程序被执行的时候,设置d属性将可使该文件(或目录)不会被dump备份
# i :让一个文件【不能被删除、改名、设置链接也无法写入或新增数据】
# 对于系统安全性有相当大的助益!只有root能设置此属性
# s :当文件设置了s属性时,如果这个文件被删除,它将会被完全的移除出这个硬盘空间,
# 所以如果误删了,完全无法救回来了喔!
# u :与s相反的,当使用u来设置文件时,如果该文件被删除了,则数据内容其实还存在磁盘中,
# 可以使用来救援该文件喔!

# 注意1:属性设置常见的是a与i的设置值,而且很多设置值必须要身为root才能设置
# 注意2:xfs文件系统仅支持 AadiS 而已
  • 由于这些属性是隐藏的性质,所以需要以lsattr才能看到这些属性。
  • 对于logfile这样的日志文件,就更需要+a这个可以增加但是不能修改旧数据与删除的参数了。

lsattr(显示文件隐藏属性)

1
2
3
4
5
lsattr [-adR] 文件或目录
# 选项与参数:
# -a :将隐藏文件的属性也显示出来;
# -d :如果接的是目录,仅列出目录本身的属性而非目录内的文件名;
# -R :连同子目录的数据也一并列出来!

6.4.3 文件特殊权限:SUID、SGID、SBIT

除了rwx权限,一些文件或目录(如/tmp)还有像s和t的特殊权限。它们与系统账号和进程管理有关。

Set UID (SUID)

s出现在文件拥有者的x权限上时,就被称为Set UID,简称为SUID的特殊权限。它有这样的功能和限制:

  • SUID权限仅对二进制程序有效(不能用在shell脚本上)
  • 执行者对于该程序需要具有x的可执行权限
  • 仅在执行该程序的过程中,执行者将具有该程序拥有者(owner)的权限。

比如passwd这个命令就是典型的SUID,普通用户不拥有/etc/shadow的修改权限,但是在执行passwd时获得了root权限,因此能成功修改/etc/shadow上自己的密码。

Set GID (SGID)

s出现在用户组的x权限上时,就被称为Set GID,简称为SGID的特殊权限。

当一个文件被设置SGID后,SGID有这样的功能和限制:

  • SGID权限仅对二进制程序有效
  • 执行者对于该程序需要具有x的可执行权限
  • 仅在执行该程序的过程中,执行者将具有该程序用户组的权限。

当一个目录被设置SGID后,SGID有这样的功能和限制:

  • 用户若对于此目录具有r与x的权限时,该用户能够进入此目录;
  • 用户在此目录下的有效用户组(effective group)将会变成该目录的用户组;
  • 若用户在此目录下具有w的权限,则用户所建立的新文件的用户组和此目录的用户组相同。

Sticky Bit (SBIT)

t出现在其他人的x权限上时,就被称为Sticky Bit,简称为SBIT的特殊权限。

SBIT只对目录有效,对与目录的作用是:

  • 当用户对一个目录具有写入权限时,仅有自己与root才有权力删除、改名、移动他自己建立的文件或目录。

SUID/SGID/SBIT权限设置

chmod设置数字权限的时候,在三位数字之前再加一位就是SUID/SGID/SBIT权限。

  • 4为SUID
  • 2为SGID
  • 1为SBIT

注意,SUID不作用于目录,SBIT不作用于文件。

有一个特别要注意的例子

1
2
3
4
chmod 7666 test
ls -l test
# 返回:
# -rwSrwSrwT 1 root root 0 Jun 16 02:53 test

注意,这里大写的S和T代表的就是无效的SUID/SGID/SBIT权限。因为user,group以及others都没有x权限,而SUID/SGID/SBIT权限实际上是借用这三者的权限,这三者因为是666都没有x权限,SUID/SGID/SBIT权限就变成无效的了。

另外也可以通过符号法设置SUID/SGID/SBIT权限,其中SUID是u+s,SGID是g+s,SBIT是o+t。

6.4.4 观察文件类型:file

如果你想要知道某个文件的基本信息,例如是属于ASCII或是数据文件或是二进制文件,且其中有没有使用到动态链接库(share library),压缩文件是使用哪一种压缩方式等信息,就可以利用 file 这个命令来查看。举例来说:

1
file 文件

6.5 命令和文件的查找

6.5.1 脚本文件的查找

which(查找【执行文件】)

这个命令是根据【PATH】这个环境变量规范的路径去查找执行文件的文件名。

1
2
3
which [-a] command
# 选项或参数:
# -a :将所有由PATH目录中可以找到的命令均列出,而不止第一个被找到的命令名称。

6.5.2 文件的查找

通常我们都是先使用whereis或者是locate来检查,如果真的找不到了才以find来查找。因为whereis只找系统中某些特定目录下面的文件,locate则是利用数据库来查找文件名,当然两者就相当的快速。而find实际查找硬盘内的文件系统状态,比较费时间也影响硬盘性能。

whereis

whereis只查找几个特定目录,并没有全系统查询,所以比find要快得多。

1
2
3
4
5
6
7
whereis [-bmsu] 文件或目录名
# 选项与参数:
# -l :可以列出whereis会去查询的几个主要目录
# -b :只找二进制格式的文件
# -m :只找在说明文件manual路径下的文件
# -s :只找source源文件
# -u :查找不在上述三个项目当中的其他特殊文件

locate / updatedb

locate的使用更简单了,在包含路径的完整文件名中,只要有kayword在其中就会被显示出来。

1
2
3
4
5
6
7
locate [-ir] keyword
# 选项与参数:
# -i :忽略大小写的差异;
# -c :不输出文件名,仅计算找到的文件数量
# -l :仅输出几行的意思,例如输出五行则是-l 5
# -S :输出 locate 所使用的数据库文件的相关信息,包括该数据库纪录的文件/目录数量等
# -r :后面可接正则表达式的显示方式

使用locate来寻找数据的时候特别的快, 这是因为locate是依据/var/lib/mlocate内的数据库记载,找出使用者输入的关键字文件名。

但是数据库的建立默认是每天执行一次,所以当你在数据库更新之前查找新建立起来的文件时,locate会返回【找不到】。这种情况下就需要使用updatedb来手动更新数据库。updatedb会根据/etc/updatedb.conf的设置去查找系统硬盘内的文件名,并更新/var/lib/mlocate内的数据库文件;因为updatedb会去查找硬盘,所以更新需要等待几分钟的时间。

find

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
26
27
28
find [PATH] [option] [action]
# 选项与参数:
# 1. 与时间有关的选项:共有-atime,-ctime与-mtime,以-mtime说明
# -mtime -n :列出在n天之内被修改过内容的文件文件名;
# -mtime +n :列出在n+1天之前被修改过内容的文件文件名;
# -mtime n :列出在n天前到n+1天前之间被修改过内容的文件文件名;
# -newer file :file为一个存在的文件,列出比file还要新的文件。
# 2. 与使用者或用户组名称有关的参数:
# -uid n :n是使用者的ID,亦即UID。UID是记录在/etc/passwd里面与帐号名称对应的数字;
# -gid n :n是用户组的ID,亦即GID。GID记录在/etc/group;
# -user name :name为使用者帐号名称;
# -group name:name为用户组名称;
# -nouser :查找拥有者不在/etc/passwd中的文件
# -nogroup :查找拥有用户组不在/etc/group中的文件
# 当你自行安装软件时,很可能该软件的属性当中并没有文件拥有者,
# 在这个时候,就可以使用 -nouser 与 -nogroup 查找。
# 3. 与文件权限及名称有关的参数:
# -name filename:查找文件名称为filename的文件;
# -size [+-]SIZE:查找比SIZE还要大(+)或小(-)的文件。这个SIZE的规格有:
# c: 代表Byte,k: 代表1024Bytes。
# -type TYPE :查找文件的类型为TYPE的,类型主要有:一般正规文件(f), 设备文件(b, c),
# 目录(d), 链接文件(l), socket(s), 及 FIFO(p)等属性。
# -perm mode :查找文件权限【刚好等于mode】的文件,这个mode为类似chmod的属性值。
# -perm -mode :查找文件权限【必须要全部包含mode的权限】的文件。
# -perm /mode :查找文件权限【包含任一mode的权限】的文件。
# 4. 额外可进行的动作:
# -exec command :command为其他指令,可以用来处理查找到的结果。
# -print :将结果打印到屏幕上,这个动作是默认动作。

二、习题解答(非官方,仅为个人练习记录)

  1. 早期的UNIX系统文件最多允许14个字符,而新的UNIX与Linux系统中,文件名最多可以使用几个字符?

    若使用ext2、ext3、ext4或xfs,255个英文字符或128个中文字符。

  2. 当一个一般文件权限为-rwxrwxrwx则表示这个文件的意义是什么?

    所有人都可以读、写和执行。

  3. 我需要将一个文件的权限改为-rwxr-xr–,请问该如何执行命令?

    1
    2
    chmod 754 filename
    chmod u=rwx,g=rx,o=r filename
  4. 若我需要更改一个文件的拥有者和用户组,该用什么命令?

    chownchgrp

  5. 请问下面的目录主要放置什么数据:/etc, /boot, /usr/bin, /bin, /usr/sbin, /sbin, /dev, /var, /log, /run

    • /etc:系统主要的配置文件。
    • /boot:开机会使用到的文件,包括Linux内核文件以及启动选项与启动所需配置文件等等。
    • /usr/bin, /bin:在单人维护模式下还能够被操作的命令。
    • /usr/sbin, /sbin:开机过程中所需要的,里面包括了开机、修复、还原系统所需要的命令。
    • /dev:设备与接口设备
    • /var:经常性变动的文件,包括缓存(cache)、日志文件(log file)以及某些软件运行所产生的文件
    • /log:日志文件
    • /run:系统开机后所产生的各项信息。
  6. 若一个文件的文件名开头为“ . ”,例如.bashrc这个文件,代表什么?另外,如何显示出这个文件名与他的相关属性?

    代表它是一个隐藏文件。使用ls -al命令。