Linux开发环境及应用·第四周·文件管理和目录管理(二)

本文整理了Linux文件与目录的管理相关知识

目录管理

...

每个目录下都必有两个文件,...,它们分别代表着当前目录和上级目录,这两个目录由系统创建和删除

$ ls -a
.  ..

主目录

每个用户都有自己独立的目录,一般是/home/用户名,可以用env命令查看环境变量HOME的值来看当前用户的主目录路径。

$ env | grep HOME
HOME=/home/featherm

大多数的shell都会把符号~解释成主目录的路径,所以可以用~代替主目录,但是要注意的是,但是~只是shell解释的,编写程序涉及路径的时候,最好不要用~,因为所用的程序函数不一定支持~的解释。

绝对路径和相对路径

路径分隔符使用的是/(不同于Windows用\),以根目录/开头的路径为绝对路径,如/home/featherm;否则为相对路径,相对路径是指相对于当前目录的路径,如:当前目录下有一文件1.txt,则路径1.txt指的是当前目录下的1.txt

当前工作目录

当前工作目录是进程属性的一部分,每个进程都有

在shell中可以用pwd命令打印当前工作目录:

$ pwd        
/home/featherm/tmp

可用cd命令改变当前工作目录,如切换到根目录:

$ cd /
$ pwd
/

若不传递参数,则回到主目录:

$ cd 
$ pwd
/home/featherm

cd是shell的一个内部命令,功能由shell完成

创建/删除目录

创建目录用命令mkdir,如下创建tmp目录:

$ mkdir tmp

添加选项-p,可自动创建路径中不存在的目录,如:

$ mkdir -p database/2019/6/17/log

删除目录用命令rmdir:

$ rmdir tmp

使用rmdir时,被删除的目录必须是空的,如果想删除非空目录,可以使用前一篇文章中介绍的rm -r dir

复制目录

前一篇文章已经介绍了,使用cp命令,添加-r选项即可:

$ cp -r dir1 dir2
cp的其它常用选项
冗长模式

选项-v,冗长(Verbose)模式:可以实时列出正在复制的n文件

增量拷贝

选项-u,增量拷贝(Update),一般用于备份目录。可根据文件的时间戳,不拷贝相同的或者过时的版本的文件,以提高速度。

命令touch可将文件最后一次修改时间设置为当前时间,但不修改文件的内容,如touch 1.txt

关于增量拷贝,Linux下还有一款工具:rsync,该工具可以远程同步目录,具体用法查看man手册:

$ man rsync

目录遍历

目录遍历主要用到命令find,该命令从指定的查找范围开始,递归地查找子目录,对满足条件的文件或目录,执行指定的动作

例:
find ver1.d ver2.d -name '*.c' -print

  • 范围:目录ver1.d和目录ver2.d
  • 条件:与名字*.c匹配
  • 动作:把查找到的文件的路径名打印出来
条件选项
-name wildcard
  • 文件名与wildcard匹配(wildcard的中文意识是通配符)
  • 通配符的解释由find完成,所以wildcard两边要有引号,否则通配符会被shell展开
  • 文件名指路径名的最后一部分
-regex pattern

整个路径名与正则表达式pattern匹配

-type
  • f 普通文件
  • d 目录
  • l 符号连接文件
  • c 字符设备文件
  • b 块设备文件
  • p 管道文件

例如,打印tmp目录下的所有文件:find tmp -type f -print

-size +/- n单位

指定文件大小,单位有c(字符),b(块,512字节),k,M,G,默认为b
如:大于10M:+10M、小于10M:-10M、等于10M:10M

-mtime +/- ndays

文件的最近修改时间离现在有多少天

-newer file

所匹配文件最近修改时间比file要晚,也就是所匹配的文件要比file新

其它条件选项
  • -user 指定文件主(所属用户)
  • -nouser 文件的所属用户已经不存在(被删除)
  • -group 文件所属用户的组

其余可查阅man手册

复合条件

可以用()-o!表示条件的“与(且)”、“或”、“非”


动作选项
-print

打印匹配的文件的路径名

-exec

对匹配的目标执行一条命令。在-exec及随后分号之间的内容作为一条命令

-ok

与-exec类似,但每一条命令执行前需操作员确认


注意:动作也可以有多个

目录遍历举例
  • find . type -d -print 从当前目录开始,打印所有目录路径
  • find / -name 'stud*' -type d -print 打印名字与stud*匹配,为目录的路径
  • find / -type f -mtime -10 -print 查找根目录下最近10天内修改过的普通磁盘文件
  • find . ! -type -d -links +2 -print 从当前目录开始查找link数大于2的非目录文件
  • find~ -size +100k '(' -name core -o -name '*.tmp' ')' -print 从主目录开始查找大于100KB的名叫core 或者 有.tmp后缀的文件或目录等
  • find ~ -size +100k \( -name core -o -name '*.tmp' \) -print 同上
  • find /lib /usr -name 'libc*.so' -exec ls -lh {} \; 对匹配条件的路径执行ls命令,其中的{}代表匹配的路径
  • find src -name '*.c' -exec grep -n -- --help {} /dev/null \; 搜索src目录下的匹配*.c的文件,并用grep搜索文件中的字符串--help,显示出行号(-n选项)。由于grep命令操作一个文件时,不显示文件名,故加上一个“虚拟的”文件/dev/null(该文件是一个特殊的设备文件,读取不到数据,是空的,写入什么数据都被丢弃)
xargs命令

上面最后一个例子的效率特别低,因为每匹配到一个路径,都要创建一个进程来执行grep命令。
可以结合xargs命令提高效率,高效率的方法应该如下:
find src -name '*.c' -print | xargs grep -n -- --help

xargs命令会把标准输入追加到它的第一个参数(grep)后面,再作为一个命令执行。

如果标准输入的数据量很大,xargs指定的处理程序会启动多个进程进行,每个进程处理一批,一般是几千个参数(命令行参数占满128K字节)。可以用-n选项指定每批处理最多多少个参数

xargs常用场景:

  • shell通配符展开,超出缓冲区空间大小而失败
    rm -f *.dat 文件名*.dat展开失败,文件过多,超出缓冲区空间大小,可用xargs改造:
    ls | grep ".dat$" | xargs rm -f
  • find命中目录名因删除目录导致影响目录遍历过程
    find . -name CVS -exec rm -rf {} \; 改为:find . -name CVS -print | xargs rm -rf

打包和压缩

tar最早为顺序访问的i磁带机设备而设计(Tape ARchive 磁带归档),用于保留和恢复磁带上的文件,可用来打包和压缩文件

用法:tar ctxv[f device] file-list
第一个字母选项指定功能,必须指定,有以下三个:

  • c 创建(Create)新磁带,从头开始写,以前存于磁带上的数据会被覆盖掉
  • t 列表(Table),列出磁带上的文件名列表,当不指定文件名时,将列出所有的文件
  • x 抽取(eXtract),从磁带中抽取指定文件,当不指定文件名时,抽取所有文件
    其他选项:
  • v 冗长(Verbose),每处理一个文件就打印文件的名字,并在文件名前冠以功能字母
  • f File,指定设备文件名
  • z 采用压缩格式(gzip算法)
  • j 采用压缩格式(bzip2算法)

常用方法:

  • 打包文件:tar cvf my.tar *.[ch] makefile
  • 打包work目录:tar cvf work.tar work
  • 用gizp压缩算法打包work目录:tar cvzf work.tar.gz work (文件名的后缀只是惯例,无强制要求)
  • 恢复work目录:tar xvf work.tar.gz

gzip算法的执行速度快,但压缩比率不如bzip2;bzip2执行速度要不gzip慢很多,压缩比率较好