# 文件处理
# 文件路径
# basename
$ basename <path> # 获得一个路径的最后一段的名字
[suffix] # 去掉后缀
- 不会检查输入的路径是否实际存在。
- 例:
[root@CentOS ~]# basename /root/test.py .py test
# dirname
$ dirname <path>... # 获得路径所属的目录
- 如果输入的路径不包含 / ,则视作位于当前目录。
- 例:
[root@CentOS ~]# dirname f1 /tmp . /
# realpath
$ realpath <path>... # 将路径转换成绝对路径
- 例:
[root@CentOS ~]# realpath f1 /tmp /root/f1 /tmp
# 查看文件
# ls
$ ls [path] # 列出指定目录(默认为当前目录)下的各个文件名(不包括隐藏文件)
-a # 显示所有文件(包括隐藏文件)
-A # 与 -a 相比,不显示相对目录 . 和 ..
-l # 显示文件的详细信息
-h # 以人类容易阅读的单位显示文件大小
-d # 只显示目录本身,不显示目录下的内容
-i # 显示文件指向的 inode 号
-Z # 增加显示一列安全上下文,格式为 user:role:type:level
-S # 按文件的大小排序
-t # 按文件的 modify time 排序
- 例:
[root@CentOS ~]# ls -al total 64 dr-xr-x---. 7 root root 4096 Nov 27 19:17 . dr-xr-xr-x. 18 root root 4096 Oct 10 02:49 .. -rw------- 1 root root 6318 Dec 1 15:44 .bash_history -rw-r--r--. 1 root root 18 Dec 29 2013 .bash_logout -rw-r--r--. 1 root root 176 Dec 29 2013 .bash_profile -rw-r--r--. 1 root root 176 Dec 29 2013 .bashrc
- total 表示已显示的这些文件占用的磁盘 block 总数。
- 第一列,比如 dr-xr-x---. ,开头的 d 表示文件类型为目录,其后的 r-xr-x--- 表示文件的访问权限,末尾的 . 表示该文件使用了 SELinux 。(如果使用了 ACL 就会变成 + )
- 第二列的数字表示指向该文件的 inode 的硬链接数。
- 第三列、第四列表示文件所有者、所有者所属用户组。
- 第五列表示文件的大小(单位为 Byte)。如果该文件是目录,则不包括目录中各文件的大小。
- Nov 27 19:17 表示文件的最后修改时间。
- 最后一列表示文件名。
- 查询文件路径时,可使用以下匹配符号:
[root@CentOS ~]# touch f1 f2 f3 [root@CentOS ~]# ls f* # 通配符 * 匹配任意个字符(包括零个) f1 f2 f3 [root@CentOS ~]# ls ?1 # 通配符 ? 匹配单个字符 f1 [root@CentOS ~]# ls [a-z][0-2] # 模式匹配在字符集中的单个字符。 [a-z] 不区分大小写,而 [abc] 区分大小写 f1 f2
# du
$ du [path]... # 显示指定目录(默认为当前目录)及其子目录下的各个文件占用的磁盘空间
-a # 增加显示非目录文件
-b # 显示文件大小时,采用 bytes 单位
-h # 显示文件大小时,采用人类容易阅读的单位,比如 K、M、G
-d n # 最多显示 n 层子目录
-s # 只显示该目录占用的总磁盘空间
- 例:
du -ahd 1 # 显示当前目录下各个文件的大小,像 Windows 风格
# tree
$ tree [path]... # 按树形结构显示某个目录(默认为当前目录)下的所有文件
-a # 增加显示隐藏文件
-C # 采用不同颜色显示不同类型的文件
-L <n> # 最多显示到第 n 层子目录
-D # 显示每个文件的最后修改时间
-p # 显示每个文件的访问权限
-u # 显示每个文件的所有者
-sh # 显示文件大小时,采用人类容易阅读的单位,比如 K、M、G
- 安装:
yum install tree
# lsof
$ lsof # 显示目前所有被进程打开的文件
<filename> # 显示打开指定文件的所有进程
-p <pid> # 显示指定进程打开的所有文件
-u <uid> # 显示指定用户打开的所有文件
-i # 只显示 socket 文件
-i :22 # 只显示指定端口的 socket 文件
- 安装:
yum install lsof
- 例:
lsof | grep deleted # 查找被标记删除的文件,这些文件占用的磁盘空间尚未释放,因为这些文件依然被某些进程打开
# 查找文件
# find
$ find [path] # 显示指定目录(默认是当前目录)下的所有文件(包括子目录)
# 可选添加以下选项作为筛选条件
-maxdepth 1 # 限制搜索的目录深度(默认为无限深)
-type f # 限制文件类型,类型可以是 f、d、l、s、c 等
-empty # 筛选出内容为空的文件或目录
-name *.py # 筛选文件名,采用 shell 风格的匹配
-iname *.py # 匹配时不区分大小写(insensitive)
-path */test/* # 筛选文件路径
-ipath */test/*
-regex .*py # 筛选文件路径,采用正则匹配
-iregex .*py
-user root # 属于指定用户的文件,可以使用 uid
-group root # 属于指定用户组的文件,可以使用 gid
-perm <mode> # 文件权限等于 mode ,mode 取值可以为 0644、644、u=rw-,g=rw,o=r 等格式,按二进制位进行匹配
-perm -<mode> # 文件权限大于 mode
-size -10k # 小于 10k 的文件
-amin -3 # 过去 3 分钟之内被 access 的文件(同理还有 cmin、mmin )
-atime -3 # 过去 3 天之内被 access 的文件(同理还有 ctime、mtime )
# 可选对找到的每个文件执行一个动作
-exec echo {} \; # 执行一条命令,该命令以 \; 结尾,用 {} 嵌入文件名
-delete # 删除文件
- 筛选条件为数值类型时,有三种表示方式:
n # 等于 +n # 大于 -n # 小于
-size
选项可以使用以下单位:b # blocks ,默认采用这种 c # bytes k # kilo bytes M # Mega bytes G # Giga bytes
- 例:
[root@CentOS ~]# touch 1.py [root@CentOS ~]# ls -al total 8 drwxrwxr-x. 2 root root 28 Jan 8 11:10 . drwx------. 14 root root 4096 Jan 8 10:52 .. -rw-rw-r--. 1 root root 0 Jan 8 11:10 1.py [root@CentOS ~]# find . -name *.py ./1.py [root@CentOS ~]# find . ! -name *.py # 在筛选条件之前加冒号 ! 则表示反选 . [root@CentOS ~]# find . ! -name *.py ! -name . # 可以重复使用同一种筛选条件 [root@CentOS ~]# touch 2.py [root@CentOS ~]# find . -name *.py # 通配符 * 可能匹配当前目录下的文件,这里命令被解析成 find . -name 1.py 2.py ,需要加上引号定界符 find . -name '*.py' find: paths must precede expression: 2.py
- 例:查找并删除文件时,有多种命令写法
find . -name *.log -delete find . -name *.log -exec rm -f {} \; find . -name *.log | xargs -n 1 rm -f
# locate
$ locate [pattern] # 显示文件路径包含 pattern 的所有文件
-i # pattern 不区分大小写
-r # pattern 采用正则表达式
- 安装:
yum install mlocate
- locate 命令会从数据库 /var/lib/mlocate/mlocate.db 中查找文件,速度较快。该数据库一般每天更新一次,执行命令
updatedb
可立即更新。
# 移动文件
# rename
$ rename <源字符串> <目标字符串> <文件>... # 替换文件名中的字符串
-v # 显示每个被处理的文件
- rename 命令主要用于批量重命名文件,不能像 mv 命令一样移动文件。
# mv
$ mv <src_path>... <dst_path> # 移动文件或目录
-f # 如果目标文件已存在,则覆盖它
-i # 如果目标文件已存在,则提示用户是否进行覆盖
-u # 当目标文件不存在,或源文件比目标文件新时,才执行移动(即 update)
- mv 命令可以用于移动文件,也可以用于重命名文件(此时源路径只能有一个)。
- 如果 dst_path 已存在且是一个文件,则考虑是否覆盖目标文件。
- 如果 dst_path 已存在且是一个目录,则会将 src_path 移动到该目录之下。
- 如果是在同一文件系统内 mv 文件,则只会重命名文件路径,依然使用源文件的 inode 号 。
- 如果是跨文件系统 mv 文件,则会先拷贝源文件到目标路径(使用新的 inode 号),再删除源文件,相当于
cp f1 f2 && rm f1
。- 如果 mv 文件、文件夹的过程失败,并不会删除源文件。
- 假设在同一文件系统内操作:
mv f1 f2
- 如果 f2 不存在,则会将 f1 重命名为 f2 ,依然使用 f1 的 inode 号。
- 如果 f2 已存在,则会先删除 f2 ,再将 f1 重命名为 f2 ,依然使用 f1 的 inode 号。
mv dir1/ dir2/
- 如果 dir2 不存在,则将 dir1 重命名为 dir2 。
- 如果 dir2 已存在,则将 dir1 移动到 dir2 之下,保存为 dir2/dir1 。
- 如果 dir2/dir1 已存在且不为空,则会报错
cannot move 'dir1' to '/dir2/dir1': Directory not empty
,此时可以改用cp -rf dir1 dir2 && rm -rf dir1
。
mv dir1/* dir2/
- 将 dir1/ 目录下的所有文件移动到 dir2/ 目录下。
- 当移动多个源文件时,目标路径只能是一个目录,因此末尾不加斜杆 / 也能自动识别。
# rm
$ rm <path>... # 删除文件
-d # 删除目录(只能是空目录)
-r # 递归删除(用于删除非空目录)
-i # 若文件存在,则提示用户是否确认删除
-f # 强制删除(覆盖 -i 选项,且忽略文件不存在时的报错)
-v # 打印正在删除的文件列表
- 例:
rm -rfv * # 强制删除当前目录下的所有文件
# 切割文件
# split
$ split [file] [prefix] # 默认每隔 1000 行分割出一个子文件,子文件按 xaa、xab、xac 的格式命名,其中 prefix 默认为 x
-l 10 # --lines ,每隔 10 行分割出一个子文件
-b 10K # --bytes ,每隔 10K Bytes 分割出一个子文件,单位可以是 K、M、G、T 等
-d # 让子文件从数字 00 开始编号
--additional-suffix=.txt # 给分割出的每个子文件,添加文件扩展名
- 例:
[root@CentOS ~]# split -l 3 -d README.md README.md- [root@CentOS ~]# ls README.md README.md-00 README.md-01 README.md-02 README.md-03 README.md-04 [root@CentOS ~]# cat README.md-* > merged
# csplit
$ csplit [file] [pattern]... # 根据 pattern 分割文件。分割出的文件默认按 xx00、xx01、xx02 的格式命名
-f xx # 设置子文件名称的前缀,默认为 xx
-k # --keep-files ,当执行出错时,保留已生成的子文件。默认会全部删除
-s # --silent ,不打印每个子文件的 bytes 体积。默认会打印
--suppress-matched # 保存子文件时,排除匹配行
- 例:
csplit f1 2 # pattern 为数字时,表示从第 n 行分割出两个子文件,并且第 n 行保存到后一个子文件 csplit f1 3 6 9 # 可指定多个 pattern ,这会分割多次 csplit f1 /Hello/ # 寻找与 pattern 正则匹配的行,从每个匹配行分割文件,并且每个匹配行保存到后一个子文件 csplit f1 %^Hello% # %pattern% 表示排除匹配行之前的内容,将从匹配行开始的内容保存为子文件 csplit f1 "/^Hello World/" {5} # {n} 表示将前一个 pattern 重复执行 n 次,如果找不到匹配行则报错 csplit f1 "/^Hello World/" {*} # {*} 表示将前一个 pattern 重复执行尽可能多次,直到找不到匹配行。至少会生成一个子文件
# truncate
$ truncate [file]... # 将文件截断为指定大小。多余的空间会被丢弃,缺少的空间会用空字节填充
-s 10M # 保留从文件第一个字节开始的 10M 内容
# 其它
# md5sum
$ md5sum [file]... # 计算文件内容的 md5 哈希值
- 例:
[root@CentOS ~]# echo Hello | md5sum 09f7e02f1290be211da707a266f153b3 -
- 当文件内容改变任一字节时,哈希值都会变化。但文件属性(比如修改时间)变化时,哈希值不变。
- 另外还有 sha1sum、sha256sum、sha512sum 等其它哈希算法的命令,用法同理。
# 随机数
- 类 Unix 系统会收集一些环境噪声(比如硬件中断的时间戳的最低几位),暂存到一个熵池(entropy pool)中,用于生成随机数。
- 查看系统熵池的大小,单位为 bits :
[root@CentOS ~]# cat /proc/sys/kernel/random/entropy_avail 3754
- 用户可通过以下两个字符设备文件,获取随机数:
/dev/random
:消耗熵池来产生随机数,随机性很高,但是熵池不足时会阻塞读取它的进程。/dev/urandom
:重复使用熵池来产生随机数,随机性略低,但一般足够安全。一般读取速度为几十 MB/s ,不会阻塞。- 例:
head -c 10m /dev/urandom > f1 # 生成一个指定大小、随机内容的文件 cat /dev/urandom | tr -cd 0-9A-Za-z | head -c 12 ; echo # 生成随机字符串 echo $[`cat /dev/urandom | tr -cd 0-9 | head -c 2`%5] # 生成小于 5 的随机数