首页 > 代码库 > 探秘linux-文件管理(inode理解)及管道和IO重定向

探秘linux-文件管理(inode理解)及管道和IO重定向

一、文件管理

1、Linux系统上各主要目录的简介

/ 根,所有文件的起点 
bin 存放操作系统启动时的引导程序,以及操作系统内核文件 
boot 存放操作系统启动时的引导程序,以及操作系统内核文件 
dev 存放设备文件和特殊文件(如字符设备) 
etc 存放配置文件的目录 
home 普通用户的家目录默认都在此目录下 
lib 存放系统库和内核模块文件 (/lib/modules) 
lib64 存放x86_64位系统上共享库文件 
media 系统上提供的设备挂载点 
misc 系统上提供的设备挂载点 
mnt 系统上提供的设备挂载点 
opt 第三方应用程序的安装位置 
proc 用于输出内核与进程信息相关的虚拟文件系统 
root root用户的家目录 
sbin 存放管理员用户可执行的相关二进制程序文件目录,不能单独分区,操作系统启动时会用到该目录下的相关程序 
selinux selinux相关的安全策略等信息的存储位置 
srv 系统上运行的服务用到的数据 
sys 用于输出系统上硬件设备相关信息的虚拟文件系统 
tmp 临时文件存储位置 
usr 第三方软件的安装目录,该目录下有另一套完整的目录文件结构,包括有bin、sbin、local、include、而local又有bin、sbin等

2、inode的认识总结 
文件系统inode的一些原理:

文件系统在组织文件存储时,遵循一定的存储规则。在文件系统创建时,会将底层存储设备(硬盘)逻辑划分为一个一个的磁盘(block),一般一个block大小默认为4096个字节,也就是4K,这个值在ext系列文件系统上支持1024、2048、4096,可以在创建文件系统的时候指定(利用mke2fs -b SIZE来指定block大小,一旦指定后,后期不能更改),然后将多个磁盘块划分为一个个的块组,一个分区里面有有多个块组,但一个分区里面会有一部分block用来存储整个分区的一些属性状态的超级块,(用tune2fs -l DEVICE可以查看到分区超级块里面存储的信息,如分区卷标、分区的特性、挂载时的默认选项、总共有多少inode、总共多少block、每个块组有多少block、每个块组有多少inode等信息)。

linxu上文件有两部分组成,一个是文件的元数据,一个是文件的数据本身,两部分分开存储,文件系统划分出来的磁盘块有部分用来存储inode table,有部分用来存储数据本身,文件的数据至少占据1个block大小,即使数据只有1byte,如果blick大小为4K,那么该文件数据占用的磁盘空间也是4K。inode table里面存储每每个文件的inode条目,每个条目在在同一个文件系统内部有一个唯一的ID号,一个inode条目记录一个文件的元数据信息,这些信息包括:该文件的权限、属主属组、大小、时间戳(但是inode条目里面是没有存储该文件的文件名的,这点要注意,文件名是存储在目录文件的数据块中)。

inode条目还存储了该文件的数据所在的block的指针信息,也就是该文件数据存在哪个磁盘块上,一般一个inode条目的指针部分,分为直接指针、间接指针、二重指针、三重指针…直接指针在ext系列文件系统上有12个,一个直接指针指向一个磁盘块,故利用直接指针可以存储的数据大小,为4K*12。当数据超过48K时,就需要利用间接指针指向的数据区域来存储了,所谓间接指针就是inode的数据块指针指向了一个block块,但这个block本身存储的不是文件数据本身,而是存储的指针信息(在ext文件系统上,一个指针信息占用4字节的空间,故一个block可以有1024个指针信息),然后,由这个block块里面的指针指向具体文件数据存储磁盘块,这样,利用间接指针可以存储的文件大小为1024*4K。要存储的文件超过了间接指针能指向的范围,则需要用到二重指针,二重指针是指,inode条目里面的指针指向一个block,该block存储的依然是指针信息,一个指针指向一个block,而被指向的这个block存储的依然是指针信息,具体是这样:inode条目–>block(存的是指针)–>block(存的是指针)–>block(存的是文件数据),这样二重指针所能存储的文件数据大小就是1024*1024*4K,以此类推。

直接指针:inode条目–>block(存的是文件数据)

间接指针:inode条目–>block(存的是指针)–>block(存的是文件数据)

二重指针:inode条目–>block(存的是指针)–>block(存的是指针)–>block(存的是文件数据)

三重指针:inode条目–>block(存的是指针)–>block(存的是指针)–>block(存的是指针)–>block(存的是文件数据)

利用直接指针能存储的文件大小:12*4K

利用间接指针能存储的文件大小:1*1024*4K (一个inode条目只有1个间接指针) 
利用二重指针能存储的文件大小:1*1024*1024*4K 
利用三重指针能存储的文件大小:1*1024*1024*1024*4K

而对于文件和目录的存储,在文件系统存储时是不一样的,文件存储中,数据部分存的是文件本身的数据文件,而目录文件,数据部分存储的是目录下面文件名与该文件的inode号的对应关系

故当我们访问某个文件时,文件系统内部寻找的过程大致是这样的:(以寻找/etc/issue为例) 
首先找/根,因为根是自启动的,可以知道自己是在哪个inode上,找到/的inode后,inode指向了/下相应的数据存储的block,该block内部存储了/下一级子目录的名称和inode对应关系(当然如果/下有直接的文件,那某些数据块上存储的就是文件的数据),通过对应关系,就找到了etc所在的inode,然后通过etc的indode,就找到了etc下面的文件和目录的数据存储的block,进而找到了issue文件的数据

技术分享

3、文件类型和软硬链接的介绍

ls -l 中查看到的权限字段的信息中第一位即表示该文件的类型,常见的文件类型有:

– 表示普通文件 
d 表示目录文件 
b 表示块设备文件,如硬盘 
c 表示字符设备文件,如/dev/zero、/dev/null、/dev/ramdom 
l 表示符号链接文件 
p 表示管道文件 
s 表示socket套接字文件

硬链接:多个文件路径指向的是同一个innod,故通过innod找到的磁盘块也就是同样的特性: 
1、目录不支持硬链接 
2、硬链接不能跨文件系统 
3、创建硬链接会增加inode引用计数

硬链接创建方式:ln 原文件 链接文件

软链接:指向一个文件路径的另一个文件路径,符号链接文件本身的innod中存放磁盘块指针的位置,不是存的磁盘块指针,而是指向了另外一个路径特性: 
1、符号链接与文件时两个各自独立的文件,各有自己的inode;对原文件创建软链接,不会增加引用计数 
2、支持对目录创建符号链接,可以跨文件系统 
3、删除符号链接文件不影响原文件,但删除原文件,符号链接指定的路径即不存在,此时会变成无效的链接 
4、符号链接文件的大小,是其指向的文件的路径字符串的字节数

软链接创建方式:ln -s 原文件 链接文件

注意:创建软链接时,原始文件的路径要使用绝对路径,如果要使用相对路径,则要相对于链接文件的路径,不能是相对于当前工作目录的相对路径

4、文件系统相关命令 
cd:改变工作目录 
cd /PATH/TO/SOMEDIR 切换到指定目录 
cd 切换回家目录 
cd ~ 切换回自己家目录 
cd ~USERNAME 切换到指定用户的家目录(只有管理员才有权限切换到其他用户的家目录) 
cd – 在上一次所在目录与当前目录之间来回切换 
PWD 用来记录当前工作目录的环境变量 
OLDPWD 用来记录上一次工作目录的环境变量

ls:列出指定目录下的内容 
语法:ls [OPTION]…[FILE]… 
常用选项: 
-a 显示所有文件,包括隐藏文件 
-A 显示除.和..之外的所有文件 
-l 长格式列表,表示显示文件的详细属性信息显示出来的信息为 
-rw-r-x— 2 root root 8827 10月15 20:34 testa.log 
-rw-r-x—该文件的文件类型和相应的权限 
2 表示文件被硬链接的次数 
root 表示文件的属主 
root 表示文件的属组 
8827 表示文件的大小

但是如果对ll /dev 该处显示的是两个数字,类似brw-rw—-. 1 root cdrom 11, 0 7月13 00:34 sr0

这里的数字前一个表示主设备号,后一个表示次设备号,前一个数字一样,表示设备类型一样,后一个数字表示该种设备下的不同的设备

10月15 20:34 表示文件最后一次被修改的时间 
-h 表示对文件大小做单位换算,换算后的结果可能为非精确值(1000和1024的区别) 
-d 表示仅显示目录自身,而不是目录下面每个文件的属性,要与-l一起使用,显示目录自身的属性信息 
-r ,–reverse 表示显示时以逆序的方式进行显示,默认是升序显示 
-R ,–recursive 表示递归显示 
ls -ld 目录和符号链接信息 
ls -1 文件分行显示 
ls -S 按从大到小排序 
ls -u 配合-t,显示并按atime从新到旧排序 
ls -U不排序按目录存放顺序显示 
ls -i 可以显示文件的inode编号

stat命令:显示文件或文件系统的状态,显示文件的元数据 
例如:stat /etc/passwd 
显示大小、innod号,权限、最近一次访问时间(atime)、最近一次的更改时间(mtime)(改变文件内容),最近一次的改变时间(ctime)(改变文件元数据)

touch命令:改变文件的时间戳(atime、mtime、ctime) 
语法:touch [OPTION]…FILE… 
touch 以存在的文件,表示改变文件的三个时间戳 
touch 不存在的文件,表示新建该文件 
touch -a 已存在的文件 表示改变文件的访问时间atime 
touch -m 已存在的文件 表示改变文件的改变时间mtime 
-c 表示如果文件不存在,则不创建该文件 
-t 时间;表示修改为的时间 
例如:touch -m -t 201607211658.20 /tmp/nwc.txt 
表示修改/tmp/nwc.txt文件的修改时间为2016年07月21日16点58分20秒

cp命令:文件复制命令 
从文件系统存储级别来理解cp:分配一个空闲的inode号,在inode表中生成一个新的条目,在目录中创建一个目录项,将名称与inode编号关联,拷贝数据,生成新的文件

语法: 
单源复制:cp [OPTION]… [-T] SOURCE DEST 
多源复制:cp [OPTION]… SOURCE… DIRECTORY 
单源复制:cp [OPTION]… [-T] SOURCE DEST 
如果DEST不存在,则事先创建此文件,并复制源文件的数据至DEST中; 
如果DEST存在: 
如果DEST是非目录文件,则覆盖目标文件 
如果DEST是目录文件,则事先在DEST目录下创建一个与源文件同名的文件,并复制其数据流

多源复制:cp [OPTION]… SOURCE… DIRECTORY 
如果DEST不存在:错误 
如果DEST存在: 
如果DEST是常规文件:错误 
如果DEST是目录:分别复制每个文件至目标目录中,并保持原名 
常用选项: 
-i 覆盖之前提醒用户确认,默认cp就带此选项 
-f 强制覆盖目标文件 
-r,-R 递归复制目录及目录中的内容至目标目录 
-d 复制软链接文件本身,而不是指向的源文件 
-a 复制文件时保留文件的全部元数据信息,实现归档,可用作备份 
–preserv=LIST 指定复制时要保留那些属性信息 
mode:权限 
ownership:属主和属组 
timestamps:时间戳信息 
context:安全标签 
xattr:扩展属性 
links:符号链接 
all:上述所有属性

mv命令:文件移动命令 
(注意:同一个分区的mv操作,只是改了对应目录文件数据中针对该文件的指针信息,文件自身的inode和数据块都没发生改变,但是不同分区之间的mv操作是全部都改掉的)

从文件系统存储级别来理解mv:如果源和目标在同一个文件系统内部进行mv操作,则对应的操作相当于用新的文件名,创建对应新的目录项,删除旧的目录项及对应的旧的文件名,整个操作不会涉及到文件本身的inode号的改变和数据块的改变,只会修改inode条目上的时间戳信息,数据块的内容不会发生移动 
如果源和目标不在同一文件系统,则相当于cp和rm的操作 
语法:与cp一样 
常用选项 -i、-f 
rm命令:删除文件(建议自己建个目录文件,把要删除的文件先mv到此目录,过段时间后确认不用后,再删除) 
从文件系统存储级别来理解rm:链接数递减,取消inode与数据block之间的关联关系,释放inode号,将数据块标志为空闲状态,删除目录项。rm命令是不会删除数据块中的数据的,只是标记为空闲,让其他文件的数据可以写到该数据块,从而覆盖掉以前的数据

常用选项:-i、-f、-r 
alias 可以显示当前系统上的命令别名信息 
定义命令别名: 
alias NAME=’COMMAND’ 只对当前shell有效,立即生效,重启后失效 
例如 alias cds=‘cd /etc/sysconfig/network-scripts/’ 
撤销别名: 
umalias NAME 
例如 unalias cds 
要想永久生效,可定义在/etc/bashrc配置文件中,如果只想对某个用户永久有效,可以在该用户家目录中.bashrc中定义

tree命令 显示目录树 
-d 只显示目录 
-L LEVEL 指定显示的层级数目 
-P PARTEREN 指定显示通配符的目录 
mkdir 创建目录 
-p 递归创建,存在于不报错,且可以自动创建所需的各目录 
-v 显示详细过程 
-m MODE 创建目录时指定权限 
mkdir -pv /testdir/dir1/{x,y}/{a,b} 
mkdir -pv /testdir/dir2/{x/{a,b},y} 
mkdir -pv /testdir/dir{3,4,5/dir{6,7}} 
rmdir 删除空目录 
-p 递归删除父空目录 
-v 显示详细信息 
file命令 
语法file [OPTION] FILENAME 
选项: 
-b 显示时不显示文件名 
-f FILE 将需要判断文件类型的文件写到一个文件中,用-f指定这个文件,批量判断文件类型 
-F 显示时用指定的符号作为分隔符,默认是:冒号 
-i 显示出文件的编码类型 
-L 判断软链接时,默认只显示软链接文件本身的类型,不显示原文件的类型,加上-L后,可以显示出源文件的类型

5、通配符

匹配零个或多个任意字符 
? 匹配任意单个字符 
~ 当前用户家目录 
~USERNAME 指定用户家目录 
~+ 当前工作目录 
~- 前一个工作目录 
[0-9] 匹配一个数字范围 
[a-z] 大写和小写字母,表示aAbBcC…yYz 不包含大Z 
[A-Z] 大写和小写字母,表示AbBcC…yYzZ 不包含小a 
例如:[a-d]表示匹配 aAbBcCd 不包含大D 
但[abcd]则只匹配abcd 
[nwc9] 匹配括号内的单个字符 
[^nwc9] 匹配除括号内的字符意外的任意单个字符 
[[:digit:]] 匹配任意数字,相当于[0-9] 
[^[:digit:]] 匹配除数字之外的字符 
[[:lower:]] 匹配任意小写字母 
[[:upper:]] 匹配任意大写字母 
[[:alpha:]] 匹配任意大小字母 
[[:alnum:]] 匹配任意数字或大小写字母 
[[:space:]] 匹配空格 
[[:punct:]] 匹配标点

管道和IO重定向

1、标准输入输出介绍 
linux为程序提供三种I/O设备: 
标准输入(STDIN):0 默认是键盘 
标准输出(STDOUT):1 默认是终端窗口屏幕 
标准错误输出(STDERR):2 默认是终端窗口屏幕

2、IO重定向 
I/O重定向就是将默认标准的输入、输出、错误输出定向的别的地方 
重定向的方法:命令 重定向操作符 重定向的目标 
> 标准输出重定向,覆盖目标的内容 
>> 标准输出重定向,将结果追加到目标,不会覆盖目标的内容 
2> 标准错误输出重定向,覆盖目标的内容 
2>> 标准错误输出重定向,将结果追加到目标,不会覆盖目标的内容 
&> 标准输出和标准错误输出重定向,覆盖目标的内容 
&>> 标准输出和标准错误输出重定向,将结果追加到目标,不会覆盖目标的内容多个命令合并的输出: 
例如:(cal 2015;cal2016)>/testdir/cal.txt< 输入重定向 
例如:mail -s “help” root

tr ‘a-z’ ‘A-Z’ tr命令:转换和删除字符 
语法:tr [OPTION]… ‘SET1’ [‘SET2’] 
选项: 
-c 取字符集的补集 
-s 把连续重复的字符,以单个字符表示 
tr -s‘\n’ 表示把连续的换行符,变成1个换行符,可实现删除空白行 
-d 删除SET1匹配到的内容 
-t 将SET1的内容转换成SET2的内容 
SET支持的内容格式: 
\NNN 八进制值为NNN 的字符(1 至3 个数位) 
\ 反斜杠 
\a 终端鸣响 
\b 退格 
\f 换页 
\n 换行 
\r 回车 
\t 水平制表符 
\v 垂直制表符 
字符1-字符2 从字符1 到字符2 的升序递增过程中经历的所有字符 
[字符*] 在SET2 中适用,指定字符会被连续复制直到吻合设置1 的长度 
[字符*次数] 对字符执行指定次数的复制,若次数以 0 开头则被视为八进制数 
[:alnum:] 所有的字母和数字 
[:alpha:] 所有的字母 
[:blank:] 所有呈水平排列的空白字符 
[:cntrl:] 所有的控制字符 
[:digit:] 所有的数字 
[:graph:] 所有的可打印字符,不包括空格 
[:lower:] 所有的小写字母 
[:print:] 所有的可打印字符,包括空格 
[:punct:] 所有的标点字符 
[:space:] 所有呈水平或垂直排列的空白字符 
[:upper:] 所有的大写字母 
[:xdigit:] 所有的十六进制数 
[=字符=] 所有和指定字符相等的字符

3、管道 
管道(|)用来连接命令,例如: 
COMMAND1|COMMAND|COMMAND3… 
表示将COMMAND1的输出作为COMMAND2的输入,COMMAND的标准输出作为COMMAND3的输入 
注意:错误输出默认不能通过管道进行发送,如果要发送,可以利用2>&1或|&来实现

三、练习

1、将/etc/issue文件中的内容转换为大写后保存至/tmp/issue.out文件中 
tr ‘a-z’ ‘A-Z’ < /etc/issue >/tmp/issue.out

2、将当前系统登录用户的信息转换为大写后保存至/tmp/who.out文件中 
who|tr ‘a-z’ ‘A-Z’ >/tmp/who.out

3、一个linux用户给root发邮件,要求邮件标题为”help”,邮件正文如下:

Hello, I am 用户名,the system version is here,pleasehelp me to check it ,thanks! 
操作系统版本信息 
echo -e “hello,I am 
whoami,The system version is ,please help me to check it,thanks\nuname -sr” |mail -s “help” root

4、将/root/下文件列表,显示成一行,并文件名之间用空格隔开 
for i in 
ls /root;do echo -n “$i “;done;echo

5、file1文件的内容为:”1 2 3 4 5 6 7 8 9 10” 计算出所有数字的总和 
i=i

6、删除Windows文本文件中的’^M’字符 
cat -A /testdir/新建文本文档.txt | tr -d ‘^M’

7、处理字符串“xt.,l 1 jr#!$mn2 c*/fe3 uz4”,只保留其中的数字和空格

echo ‘xt.,l 1 jr#!$mn2 c*/fe3 uz4‘|tr -d ‘[:alpha:][:punct:]‘

8、将PATH变量每个目录显示在独立的一行 
echo $PATH|tr ‘:’ ‘\n’

9、删除指定文件的空行 
tr -s ‘\n’ ‘\n’

10、将文件中每个单词(字母)显示在独立的一行,并无空行 
tr -s ‘\n’ ‘\n’ <f1|tr ‘ ‘ ‘\n‘


探秘linux-文件管理(inode理解)及管道和IO重定向