12 shell文件的操作



12.1  文件
对于绝大部分的Linux以及UNIX系统管理员来说,他们每天面对的都是各种类型的文件,包括系统配置的更改、软件的安装以及调试。因此,了解Linux中的文件的基础知识非常重要。本节将介绍文件的类型以及文件的权限等。

12.1.1  列出文件
Linux提供了ls命令来列出某个目录的内容,其基本语法如下:
ls [option]... [file]...
在上面的语法中,option表示ls命令的选项。file参数表示文件名。

12.1.2  文件类型
1.普通文件
2.目录
3.伪文件

12.1.3  文件的权限
Unix使用一套简单有效的方式来为文件设置权限。我们再次浏览一下上面的ls -l命令的输出结果,该结果一共有7列,其中第1列就是文件的权限,如下:
-rwxr-xr-x
第1个字符是“-”,这个字符表示当前的文件是一个普通文件,不属于权限的范围。从第2个字符开始一直到结尾的9个字符代表了当前文件的存取权限。

12.2  查找文件
文件的搜索是UNIX以及Linux中经常用到的操作。在Shell程序设计的时候,也经常用到文件搜索。Linux提供了几个关于文件搜索的命令,例如locate、whereis以及find等。其中,find命令的功能最为强大,所以本节详细介绍find命令在Shell程序中的使用方法。

12.2.1  find命令以及语法
简单地讲,find命令的基本思想就是搜索一个或者多个目录树,根据用户指定的测试条件,查找符合特定标准的文件。当查找完成之后,find命令将对查找到的文件执行指定的操作。这些操作可以非常简单,例如仅仅将文件名打印出来;也可以非常复杂,例如删除文件、显示文件的详细信息或者将搜索结果传递给另外一个命令。
在使用find命令的,用户通常需要提供3种信息,分别为要搜索的路径、测试条件以及操作。find命令的基本语法如下:
find path test action
其中,path参数表示要搜索的路径,用户可以同时指定多个路径,路径之间用空格隔开。test参数表示测试条件,同样,用户也可以同时指定多个测试条件,它们之间用空格隔开。action参数则表示对于搜索结果要执行的操作,如果有多个操作,则这些操作之间用空格隔开。

12.2.2  find命令:路径
find命令的路径参数表示在何处搜索指定的文件。通常情况下,路径都是一个目录名。用户可以使用相对路径、绝对路径以及简写形式来指定路径。例如,下面的命令中都是一些合法的路径:
find /usr/bin
find /
find .
find ~root

#! /bin/bash
files=`find . -name "*.sh"`
echo "$files"

#! /bin/bash
files=`find /etc /usr/local -name httpd.conf`
echo "$files"

12.2.3  find命令:测试
find命令的测试条件用来对搜索结果进行筛选。只有符合指定条件的文件才会出现在最终的搜索结果中。前面已经讲过,当用户省略测试条件时,则表示指定目录中的所有的文件都将出现在搜索结果中。

-name pattern      表示包含指定匹配模式的文件名
-iname pattern     表示包含指定匹配模式的文件名,大小写不敏感
-type type         指定文件类型
-perm mode         匹配其权限被设置为指定mode的文件
-user userid       匹配其所有者为指定用户ID的文件
-group groupid     匹配其所有者为指定组ID的文件
-size size         匹配其大小为size的文件
-empty             匹配空文件
-amin [-+]n        文件最后一次访问时间,+(-)n表示距今n分钟前(内),n恰好n分钟;
-atime [-+]n       文件最后一次访问时间,+(-)n表示距今n天以前(内),n恰好n天;
-cmin [-+]n        文件最后一次状态改变时间,+(-)n表示距今n分钟前(内),n恰好n分钟;
-ctime [-+]n       文件最后一次状态改变时间,+(-)n表示距今n天以前(内),n恰好n天;
-mmin [-+]n        文件最后一次被修改的时间,+(-)n表示距今n分钟前(内),n恰好n分钟;
-mtime [-+]n       文件最后一次被修改的时间,+(-)n表示距今n天以前(内),n恰好n天;

#! /bin/bash
files=`find /etc -type f -print | wc -l`
directories=`find /etc -type d -print | wc -l`
echo "There are $files regular files in /etc directory."
echo "There are $directories directories in /etc directory."

#! /bin/bash
file=`find /etc -name httpd.conf -print`
head -5 $file

#! /bin/bash
file=`find /etc -name "httpd.conf*" -print`
head -5 $file

#! /bin/bash
files=`find /etc -name rc[1-9].d -print`
echo "$files"

12.2.4  find命令:使用!运算符对测试求反
find命令提供了一个感叹号运算符!,用来对测试条件求反。!符号可以加在任何测试条件的前面,表示其后测试的相反条件。在使用!运算符的时候,一定要注意语法问题,即必须在!符号的左右各留一个空格,这样find命令才会正确解释!运算符。另外,为了避免Shell解释!符号,用户需要使用单引号或者反斜线将其引用起来。
例如,下面的命令搜索/data1/wwwroot目录中,除jpg文件之外的普通文件:
find /data1/wwwroot -type f \! -name "*.jpg" -print

12.2.5  find命令:处理文件权限错误信息
find命令可以在任意指定的位置中搜索指定的文件。但是,Linux系统的权限非常严格。如果当前用户对于指定的目录没有访问权限,则find命令会给出一些错误信息,

12.2.6  find命令:动作
find命令最为强大的功能在于不仅仅可以根据复杂的条件来搜索文件,而且还可以非常方便地对搜索结果进行处理。前面已经讲过find命令的语法中的第3部分的action参数就是find命令对于搜索结果的动作。

-print        默认动作,将搜索结果写入到标准输出
-fprint file  将搜索结果写入到文件
-ls           以长格式显示搜索结果
-fls file     将搜索结果以长格式写入到文件file
-delete       将搜索到的文件删除
-exec cmd {} \;  查找并执行命令,{}表示搜索到的文件名;
-ok cmd {} \;    查找并执行命令,但是需要用户确认;

#! /bin/bash
find ./tmp -name "*.php" -exec rm -f {} \;
if [ $? -eq 0  ] ;then
    echo "the files have been deleted successfully.";
else
    echo "Failed to delete files.";
fi

12.3  比较文件
通常情况下,Linux中的数据都是以文本文件的形式存储的,并且每一行为一条记录。因此,在Shell程序中处理数据的话,经常会遇到将多个数据文件中的数据进行对比分析的情况。本节将介绍Linux中最常用的两个比较文件的命令comm和diff。

12.3.1  使用comm比较文件
comm命令的作用是逐行比较两个有序的文件,其语法如下:
comm [option]... file1 file2

#! /bin/bash
p1=`comm -2 -3 students.txt students1.txt`
echo "These students only appear in students.txt:"
echo "$p1"
p2=`comm -1 -3 students.txt students1.txt`
echo "These students only appear in students1.txt:"
echo "$p2"
p3=`comm -1 -2 students.txt students1.txt`
echo "These students appear in both students.txt and students1.txt:"
echo "$p3"


#! /bin/bash
q1=`comm -2 -3 students.txt students1.txt | wc -l`
echo "These are $q1 students only appear in students.txt."
q2=`comm -1 -3 students.txt students1.txt | wc -l`
echo "These are $q2 students only appear in students1.txt."
q3=`comm -1 -2 students.txt students1.txt | wc -l`
echo "These are $q3 students appear in both students.txt and students1.txt."

12.3.2  使用diff比较文件
diff命令功能也是逐行比较多个文件的内容。所不同的是,diff命令并不要求参与比较的文件是有序的。另外,diff不仅可以比较普通文件,而且还可以比较多个目录的内容的差异。diff命令的基本语法如下:
diff [option]... files

12.4  文件描述符
在Shell程序中操作文件的时候,经常会遇到使用文件描述符的情况。使用文件描述符来操作文件,可以使得程序符合POSIX标准。本节将介绍文件描述符的基础知识、常用的文件描述符以及自定义文件描述符的方法。

12.4.1  什么是文件描述符
从形式上讲,文件描述符是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX以及Linux等操作系统。

12.4.2  标准输入、标准输出和标准错误
当用户在Shell中执行命令的时候,每个进程都和3个文件描述符相关联,并且使用这3个文件描述符来引用相关的文件。这3个文件描述符分别为标准输入、标准输出和标准错误。默认情况下,这3个文件描述符会自动创建,用户直接使用即可。
标准输入的文件描述符为0,表示默认的输入文件,即Shell需要执行命令的来源。通常情况下,标准输入为键盘,因为绝大部分的命令来自于键盘的输入。但是,标准输入也可以是文件或者其他的命令的输出,这需要使用输入重定向。
标准输出的文件描述符为1,表示默认的输出文件,即显示Shell命令的执行结果的地方。通常情况下,标准输出的设备为显示器,但是也可以是其他的文件或者设备。
标准错误的文件描述符为2,标准Shell命令的错误消息输出的地方。默认情况下,标准错误与标准输出的设备相同,也是显示器,但是也可以是其他的文件或者设备。

12.5  重定向
在Linux的输入输出中,重定向占有非常重要的地位。在编写Shell程序以及进行系统管理的时候,经常与重定向打交道。因此,对于初学者来说,搞清楚重定向的使用技巧非常有用。

12.5.1  输出重定向(覆盖)
通常情况下,所谓输出重定向是指将原本输出到标准输出的数据输出到其他的文件或者设备中。输出重定向的操作符为大于号>,其基本语法如下:
cmd > file
在上面的语法中,cmd表示Shell命令,大于号>为重定向操作符,file表示重定向的目标文件。

12.5.2  输出重定向(追加)
除了覆盖模式之外,输出重定向还有一种追加模式,其操作符为连续的两个大于号>>。>>操作符的功能与>基本相同,只是前者不会覆盖目标文件的内容,而是追加在已有文件的后面。>>操作符的基本语法如下:
cmd [n]>> file
其中cmd表示Shell命令,n为文件描述符,如果省略n,则默认值为1,即标准输出。>>操作符同样支持一组命令,语法如下:
{ cmd1;cmd2;...;  } [n]>> file

12.5.3  输入重定向
通常情况下,Shell命令会从标准输入,即键盘读取用户输入的数据。但是Shell提供了另外一种读取用户输入的机制,即从文件中获取输入,这种机制称为输入重定向,如图12-5所示。输入重定向与输出重定向非常相似,其操作符为小于号<,基本语法如下:
cmd < file
在上面的语法中,cmd表示Shell命令,file文件的内容将作为cmd命令的输入。

12.5.4  当前文档
输入重定向的另外一个用途是生成当前文档(here documents)。当前文档主要用在命令行中需要多行输入的情况,其基本语法如下:
cmd << delimiter
document
delimiter
其中,cmd表示Shell命令,<<为输入重定向操作符,delimiter为分隔符。当Shell遇到重定向操作符<<时,会一直读取用户的输入,直到遇到某一行,其中包含指定的分隔符delimiter。两个分隔符delimiter之间的行都属于命令cmd的标准输入。最后的delimiter告诉Shell,当前文档已经结束。如果没有后面的分隔符,Shell将会继续读取输入,并会永远进行下去。

12.5.5  重定向两个文件描述符
在前面的例子中,介绍了输出重定向,即把标准输出重定向到文件。除此之外,用户还可以通过重定向操作将到一个文件描述符的输出重定向到另外一个文件描述符,即复制一个文件描述符,其语法如下:
n>&m
在上面的语法中,n和m都是文件描述符。当n=1且m=2时,文件描述符1成为文件描述符2的副本,所以所有的标准标准输出都被重定向到标准错误;而当n=2,m=1时,文件描述符2成为文件描述符1的副本,所以所有的标准错误都被重定向到标准输出。当n=1时,可以省略。

12.5.6  使用exec命令分配文件描述符
用户在命令后面使用重定向操作符的时候,重定向只对当前的命令有效。用户可以使用exec命令创建新的文件描述符,并且将文件描述符绑定到文件或者另外一个文件描述符或者文件。

exec 2> file  将所有标准错误输出重定向到文件file
exec n< file  只读方式打开的文件名称file,并使用描述符n,n是大于3的
exec n> file  以写入的方式打开名称为file的文件,并使用文件描述符n,n是大于3的
exec n<> file 以读写方式打开file,并使用描述符n,n是大于3的
exec n>&-     关闭文件描述符n
exec n>&m     使得文件描述符n称为文件描述符m的副本,即将文件描述符m复制到n

# /bin/bash
exec 99>&2
exec 2> errlog
ls -lw
exec 2>&99
exec 99>&-

#!/bin/bash
echo 'START'
exec 100< <(ls -l)
num=1
while read line; do
    echo "LINE $num: $line"
    num=$(($num + 1))
done <&100
exec 100>&-        #close it
echo 'END'

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值