Linux->文件系统初识
Posted 波奇~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux->文件系统初识相关的知识,希望对你有一定的参考价值。
目录
前言:
在大家看这篇文章之前,我得提出几个问题:
1. 我们有多种对于文件的操作方式,不同的语言有不同的方式,但是对于我们的操作系统来说,它真的认识这么多语言提供的方式吗?
2. 操作文件时,都需要打开文件,但为什么打开文件?
3. 文件在操作时,文件处在什么位置?
4. 当系统中存在大量的被打开的文件,应该如何管理?
1 认识文件
所谓对于文件的操作究其本质,其实它并不关于任何一门语言,而是所有的语言都尊崇同样的接口,并且对这些接口封装,从而实现我们看到了语言的各种各样的不同的文件操作方式。这些操作在后方为大家介绍。
文件本身就是内容加上属性,所以对于文件的操作就是对于内容的操作和对其属性的操作,当我们没有使用文件时,它是安静的呆在磁盘当中。一旦我们对文件操作时,他就会从磁盘加载到内存当中,这一点相信大家了解冯诺依曼体系一定能明白。
我们在对文件进行操作的时候,文件需要内加载到内存当中,但是是否只有我们一个人在使用呢?也就是这个文件是否有多个人在对其进行打开操作?答案肯定是不可能只有一个人也就是一个进程在使用的,因为就连我们平时操作Linux时,我都能对一个文件进行多次打开。而且我在一个程序当中是可以打开多个文件的,那么我们可以得到一个结论:进程和文件的对应关系是1:n。
并且,在Liunx下,一切皆文件。
综上,系统会打开多个进程,而一个进程又会操作多个文件,那么系统中会充斥非常多的文件,这些文件是如何被管理的呢?下面就会讲解文件的加载过程和文件的管理操作。
2 文件使用
2.1 文件加载
首先,我们了解文件在没有被操作时是呆在磁盘当中的,只有在被调度时才会从磁盘加载到内存当中,然后呢?如果所有文件的操作都是到这里就戛然而止了,那么内存当中必然到处都是乱七八糟的文件,此时就必须得有一个管理的操作。
看到管理大家必须的像是触发了关键词一样,那就是先描述,再组织。没错操作系统对于文件的管理如同进程管理那般,都是先描述再组织,那么它同样是有自己抽象出来的结构体用于装载自己的信息。
struct file
//属性
//各种链接关系
看到我们结构体当中存有的数据是属性和各种链接关系,那么证明了什么?也就是说我们的文件内容与我们的管理并没有太多的关系,那么我们就让他乖乖的呆在内存当中,甚至在刚准备打开文件的时候只需要将文件的各种属性告知操作系统都行,内容慢慢的加载。
文件是由操作系统打开的,但是是我们也就是进程让操作系统打开的,那么这样我们的对于文件的操作也就变为了进程与文件的操作。
在系统当中,进程和文件都是被组织起来的数据结构,那么他们之间的交互就变成了两个结构体的操作------struct tast_struct和struct file。
所以整个文件加载到内存当中的过程就如下图:
相信看到了这一张图大家是能够将我前面所讲的内容联系起来的,当然真实的图比我这要复杂很多。这里我们将文件管理和内存管理分开来看,文件结构体里面只存有文件在内存当中的地址,也就是整个文件管理和内存管理的关系只有这样的联系,并且这个联系是随时能够被更改的。具体如何更改呢?我之后讲解。那么这样做之后有什么好处呢?实现了文件管理和内存管理的解耦操作,也就是两者都互相并不关心彼此是如何操作的,彼此都只需要一个固定的方式进行交互。
2.2 外设文件使用
操作系统想要显示内容到显示器上面,或者想要获取键盘上的信息从本质而言都是对于文件的操作,但是这样想是否有一些抽象?它怎么就能使用外设文件的信息,它是怎么搞的?但是我们可以换一个角度去想象我们的外设,如果外设是一个进程代码呢?那么它里面是不是就有了什么?代码,而代码里面有什么?函数,也就是每一个外设都是有提供自己的操作方式的,例如键盘就会有一个输入内容的操作方式,显示器就有显示内容的操作方式。
那么因为是一个函数,我们就可以做一件什么事情呢?那就是调用这个函数实现对应的功能,不过说起来简单,具体应该怎么操作呢?如下图:
请问,我们在file结构体当中定义了一个什么样的变量?函数指针,我们都知道Linux是用C语言写的,而C语言不支持在结构体里面写成员函数,所以操作系统也不会支持写成员函数,但是函数的什么是可以写在结构体当中的呢?那就是函数指针,只要有了函数指针找到对应的函数还不简单?
那么上图也就表示了,任何一个外设都有属于自己的文件,并且每一个文件都被抽象成为了一个结构体,所有信息都被记录了起来,通过函数指针调用外设本身为我们提供的操作函数。这样做就能实现对所有不同的外设做出统一的管理执行方式了。要问如果外设不按照这个规则来写呢?那我之只能说那是外设的问题,不是系统的问题。
至于上面为什么键盘只有读函数,显示器只有写函数的原因,也不是这两个没有对应的写和读函数,只是都被置位空了,调用了没有任何意义,我们总不能从键盘上写信息吧,难道让它的某个按键跳起来打人?这也太奇怪了。
3 文件接口和文件描述符
3.1 文件系统调用接口
博主在最开始的时候就已经为大家声明了,任何语言对于文件的操作都源自于封装系统给我们提供的系统调用函数,那么函数有哪些呢?
- fcntl 文件控制
- open 打开文件
- creat 创建新文件
- close 关闭文件描述字
- read 读文件
- write 写文件
- readv 从文件读入数据到缓冲数组中
- writev 将缓冲数组里的数据写入文件
- pread 对文件随机读
- pwrite 对文件随机写
博主这里也就主要使用open、close、write、read函数,主要是想要让大家了解这些接口的操作方式。
open:
文件系统调用的所有接口都在这三个文件当中,重点讲解的是它的参数,第一个参数const char* pathname,相信大家通过变量名也能够知道这是个什么参数,没错,这就是文件的位置加名字,通过字符串表示,这个没什么难的,我也不需要多讲。
第二个参数int flags,这是干嘛的?你们可能得说了,这不就是一个整数嘛,有啥,并不是,他是一个有32位的位图数据结构。什么意思?看下代码。
1 #include<stdio.h>
2
3 #define ONE 0x01
4 #define TWO 0x02
5 #define THREE 0x04
6 #define FOUR 0x08
7 #define FIVE 0x10
8
9 void Print(int flags)
10
11 if(flags & ONE) printf("ONE\\n");
12 if(flags & TWO) printf("TWO\\n");
13 if(flags & THREE) printf("THREE\\n");
14 if(flags & FOUR) printf("FOUR\\n");
15 if(flags & FIVE) printf("FIVE\\n");
16
17
18 int main()
19
20 Print(ONE);
21 printf("*******************************\\n");
22 Print(ONE | TWO);
23 printf("*******************************\\n");
24 Print(ONE | TWO | THREE);
25 printf("*******************************\\n");
26
输出:
看到了什么现象?我们通过不同的位然后输出了不同的结果,这也就是位图的作用。
而我们的open函数里面的flags也是同样的作用,只不过它提供了更多的接口罢了。如下:
除了以上接口外,还有很多接口,不过博主认为初次学习认识这些接口就行了。
O_APPEND:追加内容
O_CREAT:没有文件时创建文件
O_TRUNC:清空之前文件数据
O_RDONLY:只读
O_WRONLY:只写
O_RDWR:可读可写
操作方式:
大家可能会主要到0666,这是什么?很简单,这就是权限的意思,表示所有人都是可读可写,那么创建的log.txt的权限表示应该是-rw-rw-rw-这样才对,但是看界面:
是我们说的那样嘛?很明显不是,为什么那是因为有一个权限掩码的东西在作祟,也就是umask。怎么改呢?很简单只需要在主程序当中加一句umask(0)即可。
上述就是open函数的操作了,其余函数我也不讲解了,有兴趣的大家可以自行了解,本篇文章重点不再这里,而是open函数的返回值int fd。
3.2 文件描述符
所谓文件描述符其实也不是什么很牛逼的东西,就是一个数字,也可以说是一个数组下标,还记得我开始画的那一张图嘛?
就是这一张图,它的里面就应该有文件描述符,只不过我没有画出来罢了,如果加上就变成了如下:
我们的每一个进程里面都有自己专属的struct file结构体,这个结构体变量里面会存储大量的被打开的文件的地址,但是,我们这些文件的时候却不是通过地址去匹配,而是通过下标实现,也就是我们的文件描述符fd。
在C封装代码当中我们也是能够找到文件标识符的:
我们每打开一个进程,操作系统都会自动为我们打开三个文件分别是标准输入、标准输出、标准错误,分别对应了文件描述符0、1、2这三个位置。通过代码可以查看:
当然这都不是重点,重点是当我们知道了这三个文件的文件描述符我们就能干一件什么事情呢?那就是偷偷给他把里面的地址换了,换成我们自己的文件地址,怎么说呢?也就是重定向功能,比如本来应该输出到显示器上的代码,现在却跑到了我自己的文件中去了。如下:
当我们没有关闭1号文件,那么这个时候的1号文件就是stdout对应的文件,那么输出的方式就是在显示器上表示出来,看结果:
和我们预想的一模一样,那么我们将1号文件关闭,再自己在后面打开一个文件,请看发生了什么。
看到了吗?我们的输出跑到了log.txt文件当中去了,整个过程我就关闭了1号文件,然后创建了一个文件,而且创建的文件的文件标识符又变成了1,这说明了什么?
这证明了,文件描述符的存储方式根据顺序排列,如果前面有小的描述符,那么这个文件就会去占据哪一个位置。
此时,咱们就实现了流的重定向功能,但是这样做有点太挫了,看不下去,还要先去关闭一个文件才能重新指向一个新的文件,所以还有一个接口dup(),就是用来替换这种无语的操作的,看下方:
当然,一般来说我们都是用dup2()来替换的,其中的两个参数表示,将oldfd去指向newfd,表示了关闭原来的newfd,成为现在的oldfd。这样讲有点绕,图解:
看到了吗?我们并没有改变log.txt的指向,也没有关闭1号文件,但是我们输出内容时,都会被存到log.txt文件当中,还可以看到log.txt的文件描述符不是1而是3,这就表明了,我们将1号位置的文件地址变为了log.txt,3号还是三号。
4 缓冲区
对于缓冲区,博主不想说过多,不过基础的知识可以提及一些,缓冲区在系统当中是没有这个玩意的,缓冲区的实现和我们平时写的代码是一个级别的东西,都是用户层代码。平时我们看不到它,但是它却存在的原因是因为有库文件为我们维护了,它的实现很复杂也很牛逼,博主也不明白,可能以后会明白,但是我知道缓冲区有三种刷新方式。
无缓冲:内容直接刷新
行缓冲:遇到一个\\n刷新
全缓冲:缓冲区满了或者程序结束了刷新
对于这个的理解我用一段奇怪的代码,大家就能够理解了:
这没什么,不就是把数据输出嘛,也没什么不对,但是请看下面:
我们重定向到log.txt文件当中发生了什么?先输出的write,然后在输出了两个printf,这很奇怪不是吗?其实不然,如果我们知道了缓冲区就知道了怎么回事。
write是系统调用,所以没有缓冲区,但是printf呢,有缓冲区,并且因为有fork()创建了一个子进程,那么这个时候缓冲区的内容同时被父子进程都获取到了,但是程序结束需要刷新缓冲区,这个时候就会发生什么?父进程或者子进程都会区刷新缓冲区,但是缓冲区只有一个数据,怎么办呢?那么这个时候就会出现写时拷贝的这个过程,也就表示了会出现两个hello printf。
出现这个现象,究其原因其实就是我们的文件重定向之后,将缓冲区刷新方式冲行缓冲变为了什么?全缓冲。
以上,就是我对文件初认识的全部理解,希望能对大家有帮助。
linux从初识到入门_文件系统
基础目录名称及作用规定
Filesystem Hierarchy Standard #标准文件系统目录 即FHS
/bin:所有用户可用的基本命令程序文件;
/sbin:供系统管理使用的工具程序;
/boot:引导加载器必须用到的各静态文件:kernel, initramfs(initrd), grub等;
/dev:存储特殊文件或设备文件;
设备有两种类型:字符设备(线性设备)、块设备(随机设备);
/etc:系统程序的配置文件,只能为静态;
/home:普通的家目录的集中位置;一般每个普通用户的家目录默认为此目录下与用户名同名的子目录,/home/USERNAME;
/root:管理员的家目录;可选;
/lib:为系统启动或根文件系统上的应用程序(/bin, /sbin等)提供共享库,以及为内核提供内核模块
libc.so.*:动态链接的C库;
ld*:运行时链接器/加载器;
modules:用于存储内核模块的目录;
/lib64:64位系统特有的存放64位共享库的路径;
/media:便携式设备挂载点,cdrom, floppy等;
/mnt:其它文件系统的临时挂载点;
/opt:附加应用程序的安装位置;可选路径;
/srv:当前主机为服务提供的数据;
/tmp:为那些会产生临时文件的程序提供的用于存储临时文件的目录;可供所用户执行写入操作;有特殊权限;
/usr:usr Hierarchy,全局共享的只读数据路径;
bin, sbin
lib, lib64
include:C程序头文件;
share:命令手册页和自带文档等架构特有的文件的存储位置
local:另一个层级目录;
X11R6:X-Window程序的安装位置
src:程序源码文件的存储位置
/usr/local:Local hierarchy,让系统管理员安装本地应用程序;也通常用于安装第三方程序;
/var:/var Hierarchy,存储常发生变化的数据的目录;
cache Application cache data #程序缓存数据
lib Variable state information #数据的变化情况
local Variable data for /usr/local #可变的local 数据
lock Lock files #锁文件
log Log files and directories #日志和目录文件
opt Variable data for /opt #变化的opt数据
run Data relevant to running processes #与运行过程有关的数据
spool Application spool data
tmp Temporary files preserved between system reboots #系统重启时保存的临时文件
/proc:基于内存的虚拟文件系统,用于为内核及进程存储其相关信息;它们多为内核参数,例如net.ipv4.ip_forward, 虚拟为net/ipv4/ip_forward, 存储于/proc/sys/, 因此其完整路径为/proc/sys/net/ipv4/ip_forward;
/sys:sysfs虚拟文件系统提供了一种比proc更为理想的访问内核数据的途径;
其主要作用在于为管理Linux设备提供一种统一模型的的接口;
Linux系统上的文件类型:
-:常规文件;即f;
d: directory,目录文件;
b: block device,块设备文件,支持以“block”为单位进行随机访问
c:character device,字符设备文件,支持以“character”为单位进行线性访问
major number:主设备号,用于标识设备类型,进而确定要加载的驱动程序
minor number:次设备号,用于标识同一类型中的不同的设备;
8位二进制:0-255
l:symbolic link,符号链接文件;
p: pipe,命名管道;
s: socket,套接字文件;
基本命令:
命令类型:
外部命令
shell内嵌命令
type COMMAND:
内部:builtin
外部:显示为命令文件路径;
注意:命令可以有别名;别名可以与原名相同,此时原名被隐藏;此时如果要运行原命令,则使用\COMMAND;
命令别名:
获取所有可用别名的定义:
~]# alias
定义别名:
~]# alias NAME=‘COMMAND‘
注意:仅对当前shell进程有效
撤销别名:
~]# unalias NAME
which命令:
which - shows the full path of (shell) commands
which [options] programname [...]
--skip-alias:忽略别名
[[email protected] ~]# which ls
alias ls=‘ls --color=auto‘
/usr/bin/ls
whereis命令:
whereis - locate the binary, source, and manual page files for a command
whereis [options] name...
-b: 仅搜索二进制程序路径;
-m:仅搜索使用手册文件路径;
who命令:
who - show who is logged on #查看当前登录的用户
who [OPTION]...
-b: 系统此次启动的时间;
-r: 运行级别;
w命令:
w - Show who is logged on and what they are doing.
#查看登录的用户及用户在做什么
bash的基础特性之一:
命令历史:shell进程会在其会话中保存此前用户提交执行过的命令;
~]# history
定制history的功能,可通过环境变量实现:
HISTSIZE:shell进程可保留的命令历史的条数;
HISTFILE:持久保存命令历史的文件;
.bash_history
HISTFILESIZE:命令历史文件的大小;
命令用法:
history [-c] [-d 偏移量] [n]
或 history -anrw [文件名]
或 history -ps 参数 [参数...]
-c: 清空命令历史;
-d offset:删除指定命令历史
-r: 从文件读取命令历史至历史列表中;
-w:把历史列表中的命令追加至历史文件中;
history #:显示最近的#条命令;
调用命令历史列表中的命令:
!#:再一次执行历史列表中的第#条命令;
!!:再一次执行上一条命令;
!STRING:再一次执行命令历史列表中最近一个以STRING开头的命令;
注意:命令的重复执行有时候需要依赖于幂等性;
调用上一条命令的最后一个参数:
快捷键:ESC, .
字符串:!$
控制命令历史记录的方式:
环境变量:HISTCONTROL
ignoredups:忽略重复的命令;
ignorespace:忽略以空白字符开头的命令;
ignoreboth:以上两者同时生效;
修改变量的值:
NAME=‘VALUE‘
Linux基础知识
bash的基础特性:
命令补全:
shell程序在接收到用户执行命令的请求,分析完成之后,最左侧的字符串会被当作命令;
命令查找机制:
查找内部命令;
根据PATH环境变量中设定的目录,自左而右逐个搜索目录下的文件名;
给定的打头字符串如果能惟一标识某命令程序文件,则直接补全;
不能惟一标识某命令程序文件,再击tab键一次,会给出列表;
路径补全:
在给定的起始路径下,以对应路径下的打头字串来逐一匹配起始路径下的每个文件:
tab:
如果能惟一标识,则直接补全;
否则,再一次tab,给出列表;
目录管理类的命令:
mkdir, rmdir
mkdir:make directories #创建目录
mkdir [OPTION]... DIRECTORY...
-p: 自动按需创建父目录;
[[email protected] ~]# mkdir /tmp/test/test.txt
mkdir: 无法创建目录"/tmp/test/test.txt": 没有那个文件或目录
[[email protected] ~]# mkdir -p /tmp/test/test.txt
-v: verbose,显示详细过程;
[[email protected] ~]# mkdir -p -v /tmp/test2/test.txt
mkdir: 已创建目录 "/tmp/test2"
mkdir: 已创建目录 "/tmp/test2/test.txt"
-m MODE:直接给定权限;
注意:路径基名方为命令的作用对象;基名之前的路径必须得存在;
rmdir:remove empty directories #删除目录文件
rmdir [OPTION]... DIRECTORY...
-p:删除某目录后,如果其父目录为空,则一并删除之;
[[email protected] ~]# mkdir -p /tmp/test/test1/test.txt
[[email protected] ~]# rmdir -p /tmp/test/test1/test.txt/
rmdir: 删除目录 "/tmp" 失败: 设备或资源忙
-v: 显示过程;
[[email protected] ~]# rmdir -pv /tmp/test/test1/test.txt/
rmdir: 正在删除目录 "/tmp/test/test1/test.txt/"
rmdir: 正在删除目录 "/tmp/test/test1"
rmdir: 正在删除目录 "/tmp/test"
rmdir: 正在删除目录 "/tmp"
rmdir: 删除目录 "/tmp" 失败: 设备或资源忙
问题1:如何创建/tmp/x/y1, /tmp/x/y2, /tmp/x/y1/a, /tmp/x/y1/b?
命令展开机制
[[email protected] ~]# mkdir -pv /tmp/x/{y1/{a,b},y2}
mkdir: 已创建目录 "/tmp/x"
kdir: 已创建目录 "/tmp/x/y1"
mkdir: 已创建目录 "/tmp/x/y1/a"
mkdir: 已创建目录 "/tmp/x/y1/b"
mkdir: 已创建目录 "/tmp/x/y2"
问题2:如何创建a_c, a_d, b_c, b_d;
[[email protected] ~]# mkdir -v {a,b}_{c,d}
mkdir: 已创建目录 "a_c"
mkdir: 已创建目录 "a_d"
mkdir: 已创建目录 "b_c"
mkdir: 已创建目录 "b_d"
bash的基础特性之:命令行展开
~:自动展开为用户的家目录,或指定的用户的家目录;
{}:可承载一个以逗号分隔的路径列表,并能够将其展开为多个路径;
例如:/tmp/{a,b} 相当于 /tmp/a /tmp/b
问题1:mkdir -pv /tmp/x/{y1/{a,b},y2}
问题2:mkdir -v {a,b}_{c,d}
问题3:创建如下目录结构:
/tmp/mysysroot/
|-- bin
|-- etc
| `-- sysconfig
| `-- network-scripts
|-- sbin
|-- usr
| |-- bin
| |-- lib
| |-- lib64
| |-- local
| | |-- bin
| | |-- etc
| | |-- lib
| | `-- sbin
| `-- sbin
`-- var
|-- cache
|-- log
`-- run
~]# mkdir -pv /tmp/mysysroot/{bin,sbin,etc/sysconfig/network-scripts,usr/{bin,sbin,local/{bin,sbin,etc,lib},lib,lib64},var/{cache,log,run}}
[[email protected] ~]# mkdir -pv /tmp/mysysroot/{bin,sbin,etc/sysconfig/network-scripts,usr/{bin,sbin,local/{bin,sbin,etc,lib},lib,lib64},var/{cache,log,run}}
mkdir: 已创建目录 "/tmp/mysysroot"
mkdir: 已创建目录 "/tmp/mysysroot/bin"
mkdir: 已创建目录 "/tmp/mysysroot/sbin"
mkdir: 已创建目录 "/tmp/mysysroot/etc"
mkdir: 已创建目录 "/tmp/mysysroot/etc/sysconfig"
mkdir: 已创建目录 "/tmp/mysysroot/etc/sysconfig/network-scripts"
mkdir: 已创建目录 "/tmp/mysysroot/usr"
mkdir: 已创建目录 "/tmp/mysysroot/usr/bin"
mkdir: 已创建目录 "/tmp/mysysroot/usr/sbin"
mkdir: 已创建目录 "/tmp/mysysroot/usr/local"
mkdir: 已创建目录 "/tmp/mysysroot/usr/local/bin"
mkdir: 已创建目录 "/tmp/mysysroot/usr/local/sbin"
mkdir: 已创建目录 "/tmp/mysysroot/usr/local/etc"
mkdir: 已创建目录 "/tmp/mysysroot/usr/local/lib"
mkdir: 已创建目录 "/tmp/mysysroot/usr/lib"
mkdir: 已创建目录 "/tmp/mysysroot/usr/lib64"
mkdir: 已创建目录 "/tmp/mysysroot/var"
mkdir: 已创建目录 "/tmp/mysysroot/var/cache"
mkdir: 已创建目录 "/tmp/mysysroot/var/log"
mkdir: 已创建目录 "/tmp/mysysroot/var/run"
[[email protected] ~]# tree /tmp/mysysroot/
/tmp/mysysroot/
|-- bin
|-- etc
| `-- sysconfig
| `-- network-scripts
|-- sbin
|-- usr
| |-- bin
| |-- lib
| |-- lib64
| |-- local
| | |-- bin
| | |-- etc
| | |-- lib
| | `-- sbin
| `-- sbin
`-- var
|-- cache
|-- log
tree命令:
tree [options] [directory]
-L level:指定要显示的层级;
bash的基础特性:命令的执行状态结果
命令执行的状态结果:
bash通过状态返回值来输出此结果:
成功:0
失败:1-255
命令执行完成之后,其状态返回值保存于bash的特殊变量$?中;
命令正常执行时,有的还回有命令返回值:
根据命令及其功能不同,结果各不相同;
引用命令的执行结果:
$(COMMAND)
或`COMMAND` #反引号
bash的基于特性:引用
强引用:‘‘
弱引用:""
命令引用:``
bash基础特性:快捷键
Ctrl+a:跳转至命令行行首
Ctrl+e:跳转至命令行行尾
Ctrl+u:删除行首至光标所在处之间的所有字符;
Ctrl+k:删除光标所在处至行尾的所有字符;
Ctrl+l:清屏,相当于clear
文件查看类命令:cat, tac, head, tail, more, less
分屏查看命令:more和less
more命令:
more FILE
特点:翻屏至文件尾部后自动退出;
less命令:
less FILE
特点:翻页至文件尾部不退出
head命令:
查看文件的前n行;
head [options] FILE
-n # 前n行
-#
tail命令:
查看文件的后n行;
tail [options] FILE
-n # 后n行
-#
-f:查看文件尾部内容结束后不退出,跟随显示新增的行;
stat命令:
stat - display file or file system status
stat FILE...
文件:两类数据
元数据:metadata
数据: data
时间戳:
access time:2015-12-10 16:12:22.776423693 +0800 #最近一次访问时间
modify time:2015-12-10 16:12:22.776423693 +0800 #最近一次修改时间
change time:2015-12-10 16:12:22.776423693 +0800 #最后一次改动时间
touch命令:
touch - change file timestamps
touch [OPTION]... FILE...
-c: 指定的文件路径不存在时不予创建;
-a: 仅修改access time;
-m:仅修改modify time;
-t STAMP
[[CC]YY]MMDDhhmm[.ss]
文件管理工具:cp, mv, rm
cp命令:copy
源文件;目标文件;
单源复制:cp [OPTION]... [-T] SOURCE DEST
多源复制:cp [OPTION]... SOURCE... DIRECTORY
cp [OPTION]... -t DIRECTORY SOURCE...
单源复制:cp [OPTION]... [-T] SOURCE DEST
如果DEST不存在:则事先创建此文件,并复制源文件的数据流至DEST中;
如果DEST存在:
如果DEST是非目录文件:则覆盖目标文件;
如果DEST是目录文件:则先在DEST目录下创建一个与源文件同名的文件,并复制其数据流;
多源复制:cp [OPTION]... SOURCE... DIRECTORY
cp [OPTION]... -t DIRECTORY SOURCE...
如果DEST不存在:错误;
如果DEST存在:
如果DEST是非目录文件:错误;
如果DEST是目录文件:分别复制每个文件至目标目录中,并保持原名;
常用选项:
-i:交互式复制,即覆盖之前提醒用户确认;
-f:强制覆盖目标文件;
-r, -R:递归复制目录;
-d:复制符号链接文件本身,而非其指向的源文件;
-a:-dR --preserve=all, archive,用于实现归档;
--preserv=
mode:权限
ownership:属主和属组
timestamps: 时间戳
context:安全标签
xattr:扩展属性
links:符号链接
all:上述所有属性
mv命令:move
mv [OPTION]... [-T] SOURCE DEST
mv [OPTION]... SOURCE... DIRECTORY
mv [OPTION]... -t DIRECTORY SOURCE..
常用选项:
-i:交互式;
-f:force
rm命令:remove #删除
rm [OPTION]... FILE...
常用选项:
-i:interactive
-f:force
-r: recursive
删除目录:rm -rf /PATH/TO/DIR
危险操作:rm -rf /*
注意:所有不用的文件建议不要直接删除,而是移动至某个专用目录;(模拟回收站)
变量:
命名的内存空间;
变量类型:
字符型:
数值型
精确数值:
近似数值:
存储格式、数据范围、参与运算;
变量的赋值操作:
name=tom
globbing:文件名通配(整体文件名匹配,而非部分)
匹配模式:元字符
*:匹配任意长度的任意字符
pa*, *pa*, *pa, *p*a*
pa, paa, passwd
?:匹配任意单个字符
pa?, ??pa, p?a, p?a?
pa, paa, passwd
[]:匹配指定范围内的任意单个字符
有几种特殊格式:
[a-z], [A-Z], [0-9], [a-z0-9]
[[:upper:]]:所有大写字母
[[:lower:]]:所有小写字母
[[:alpha:]]:所有字母
[[:digit:]]:所有数字
[[:alnum:]]:所有的字母和数字
[[:space:]]:所有空白字符
[[:punct:]]:所有标点符号
pa[0-9][0-9], 2[0-9][0-9]
[^]:匹配指定范围外的任意单个字符
[^[:upper:]]
[^0-9]
[^[:alnum:]]
显示/var目录下所有以l开头,以一个小写字母结尾,且中间出现一位任意字符的文件或目录;
ls -d /var/l?[[:lower:]]
[[email protected] ~]# ls -d /var/l?[[:lower:]]
/var/lib /var/log
显示/etc目录下,以任意一位数字开头,且以非数字结尾的文件或目录;
ls -d /etc/[0-9]*[^0-9]
显示/etc目录下,以非字母开头,后面跟一个字母及其它任意长度任意字符的文件或目录;
ls -d /etc/[^a-z][a-z]*
复制/etc目录下,所有以m开头,以非数字结尾的文件或目录至/tmp/magedu.com目录;
cp -r /etc/m*[^0-9] /tmp/magedu.com/
复制/usr/share/man目录下,所有以man开头,后跟一个数字结尾的文件或目录至/tmp/man/目录下;
cp -r /usr/share/man/man[0-9] /tmp/man/
复制/etc目录下,所有以.conf结尾,且以m,n,r,p开头的文件或目录至/tmp/conf.d/目录下;
cp -r /etc/[mnrp]*.conf /tmp/conf.d/
IO重定向及管道
程序:指令+数据
程序:IO
可用于输入的设备:文件
键盘设备、文件系统上的常规文件、网卡等;
可用于输出的设备:文件
显示器、文件系统上的常规文件、网卡等;
程序的数据流有三种:
输入的数据流;<-- 标准输入(stdin),键盘;
输出的数据流:--> 标准输出(stdout),显示器;
错误输出流: --> 错误输出(stderr),显示器;
fd: file descriptor,文件描述符
标准输入:0
标准输出:1
错误输出:2
IO重定向:
输出重定向:>
特性:覆盖输出 #该操作会覆盖文件
输出重定向:>>
特性:追加输出 #在文末追加
# set -C #c为大写
禁止覆盖输出重定向至已存在的文件;
此时可使用强制覆盖输出:>|
[[email protected] ~]# set -C
[[email protected] ~]# echo ‘hello ‘ >fstab
-bash: fstab: 无法覆盖已存在的文件
[[email protected] ~]# echo ‘hello ‘ >| fstab
# set +C
关闭上述特性
注意:该设定,仅对当前shell进程有效。
错误输出流重定向:
2> 覆盖输出
2>> 追加输出
合并正常输出流和错误输出流:
(1) &>, &>>
(2) COMMAND > /path/to/somefile 2>&1 #覆盖输出并合并错误输出
COMMAND >> /path/to/somefile 2>&1#追加输出并合并错误输出
[[email protected] ~]# echo ‘hello ‘ > ./fstab 2>&1 #将hello覆盖输出并合并错误输出重定向
[[email protected] ~]# echo $? #显示错误输出重定向的结果
0
特殊设备:/dev/null #可以将不需要的文件转移至此文件目录下,会自动删除
输入重定向:<
tr命令:
tr [OPTION]... SET1 [SET2]
把输入的数据当中的字符,凡是在SET1定义范围内出现的,通通对位转换为SET2出现的字符
用法1:
tr SET1 SET2 < /PATH/FROM/SOMEFILE
用法2:
tr -d SET1 < /PATH/FROM/SOMEFILE
注意:不修改原文件
Here Document:<<
cat << EOF
cat > /PATH/TO/SOMEFILE << EOF
管道:连接程序,实现将前一个命令的输出直接定向后一个程序当作输入数据流
COMMAND1 | COMMAND2 | COMMAND3 | ...
#[[email protected] ~]# cat /etc/issue
#\S
#Kernel \r on an \m
#[[email protected] ~]# cat /etc/issue | tr [a-z] [A-Z] | tr -d [[:upper:]]
#\
# \ \
tee命令:
COMMAND | tee /PATH/TO/SOMEFILE
tr : 主要是将文件转化后并输出
tee : 将文件一份保存一份作为下个程序的输入数据流
以上是关于Linux->文件系统初识的主要内容,如果未能解决你的问题,请参考以下文章