Linux_Shell脚本学习第三章-以文件之名(上)

一、生产任意大小的文件

包含随机数据的文件可用于测试。你可以使用这种文件测试应用程序效率,确定应用程序没有输入方面的缺陷和大小方面的限制,创建环回文件系统(环回文件自身包含文件系统,这种文件可以像物理设备一样使用mount命令进行挂载)等。Linux提供了一些可用于构建此类文件的实用工具。

1.1 dd

dd命令会克隆给定的输入内容,然后将一模一样的一份副本写入到输出。stdin、设备文件、普通文件等都可作为输入,stdout、设备文件、普通文件等也可作为输出。

$ dd if=/dev/zero of=junk.data bs=1M count=1
1+0 records in
1+0 records out
1048576 bytes (1.0 MB) copied, 0.00767266 s, 137 MB/s

该命令会创建一个内容全部为零的1MB大小的文件junk.data。
来看一下命令参数:
 if表示输入文件(input file);
 of表示输出文件(output file);
 bs指定了以字节为单位的块大小(block size);
 count表示需要被复制的块数。
块大小(bs)可以使用各种计量单位,如下图。
在这里插入图片描述
如果不指定输入参数(if),dd会从stdin中读取输入。如果不指定输出参数(of),则dd会使用stdout作为输出。
使用dd命令也能够用来测量内存操作的速度,这可以通过向/dev/null传输大量数据并观察命令输出来实现(例如,在前一个例子中显示出的1048576 bytes (1.0 MB) copied,0.00767266 s, 137 MB/s)。

二、文本文件的交集与差集

2.1 comm

comm命令可用于比较两个已排序的文件。它可以显示出第一个文件和第二个文件所独有的行以及这两个文件所共有的行。该命令有一些选项可以禁止显示指定的列,以便于执行交集和求差操作。
 交集(intersection):打印出两个文件所共有的行。
 求差(difference):打印出指定文件中所包含的互不相同的那些行。
 差集(set difference):打印出包含在文件A中,但不包含在其他指定文件(例如B和C)中的那些行。

需要注意的是comm必须使用两个排过序的文件作为输入。下面是我们用到的输入文件:

$ cat A.txt
apple
orange
gold
silver
steel
iron

$ cat B.txt
orange
gold
cookies
carrot
$ sort A.txt -o A.txt ; sort B.txt -o B.txt

2.1.1 不带任何选项

$ comm A.txt B.txt
apple
		carrot
		cookies
				gold
iron
				orange
silver
steel

输出的第一列包含只在A.txt中出现的行,第二列包含只在B.txt中出现的行,第三列包含A.txt和B.txt中共有的行。各列之间以制表符(\t)作为分隔符。

2.1.2 打印两个文件的交集

为了打印两个文件的交集,我们需要删除前两列,只打印出第三列。-1选项可以删除第一列,-2选项可以删除第二列,最后留下的就是第三列:

$ comm A.txt B.txt -1 -2
gold
orange

2.1.3 打印出两个文件中互不相同的那些行

$ comm A.txt B.txt -3
apple
		carrot
		cookies
iron
silver
steel

可以使用tr(在第2章中讲到过)删除制表符来合并两列:

$ comm A.txt B.txt -3 | tr -d '\t'
apple
carrot
cookies
iron
silver
steel

2.1.4 打印出两个文件差集

A.txt的差集

$ comm A.txt B.txt -2 -3

B.txt的差集

$ comm A.txt B.txt -1 -3

三、文件权限、所有权与粘滞位

ls命令的-l选项可以显示出包括文件类型、权限、所有者以及组在内的多方面信息:

-rw-r--r-- 1 slynux users 2497 2010-02-28 11:22 bot.py
drwxr-xr-x 2 slynux users 4096 2010-05-27 14:31 a.py
-rw-r--r-- 1 slynux users 539 2010-02-10 09:11 cl.pl

第1列表明了文件类型。
 -:普通文件。
 d:目录。
 c:字符设备。
 b:块设备。
 l:符号链接。
 s:套接字。
 p:管道。

接下来的9个字符可以划分成三组,每组3个字符(— --- —)。第一组的3个字符对应用户权限(所有者),第二组对应用户组权限,第三组对应其他用户权限。这9个字符(即9个权限)中的每一个字符指明是否其设置了某种权限。如果已设置,对应位置上会出现一个字符,否则出现一个-,表明没有设置对应的权限。

目录有一个叫作粘滞位(sticky bit)的特殊权限。如果目录设置了粘滞位,只有创建该目录的用户才能删除目录中的文件,就算用户组和其他用户也有写权限,仍无能无力。粘滞位出现在其他用户权限组中的执行权限(x)位置。它使用t或T来表示。如果没有设置执行权限,但设置了粘滞位,就使用T;如果同时设置了执行权限和粘滞位,就使用t。例如:

------rwt , ------rwT

设置目录粘滞位的一个典型例子就是/tmp,也就是说任何人都可以在该目录中创建文件,但只有文件的所有者才能删除其所创建的文件。

3.1 chmod

3.1.1 设置权限

假设需要设置权限:rwx rw- r-。
可以像下面这样使用chmod:

$ chmod u=rwx g=rw o=r filename

命令中用到的选项如下。
 u:指定用户权限。
 g:指定用户组权限。
 o:指定其他用户权限。

3.1.2 为某用户添加权限

可以用+为用户、用户组和其他用户添加权限,用-取消权限。
为已经具有权限rwx rw- r-的文件添加可执行权限:

$ chmod o+x filename

该命令为其他用户添加了x权限。

给所有权限类别(即用户、用户组和其他用户)添加可执行权限:

$ chmod a+x filename

3.1.3 删除权限

如果需要删除权限,则使用-,例如:

$ chmod a-x filename

3.2 权限表示

权限也可以使用3位八进制数来表示,每一位按顺序分别对应用户、用户组和其他用户。
读、写和执行权限都有与之对应的唯一的八进制数:

 r =  4
 w = 2
 x = 1

我们可以相加权限对应的八进制值得到所需的权限组合。例如:

 rw- = 4 + 2 = 6
 r-x = 4 + 1 = 5

权限rwx rw- r–的数字表示形式如下:

 rwx = 4 + 2 + 1 = 7
 rw- = 4 + 2 = 6
 r-- = 4

因此,rwx rw- r-- 等于764,那么使用八进制值设置权限的命令为:

$ chmod 764 filename

3.2 更改文件所有权

可以使用chown命令更改文件或目录的所有权:

$ chown user:group filename

例如:

$ chown slynux:users test.sh

在这里,slynux是用户名,users是组名。

3.3 设置粘滞位

粘滞位可以应用于目录。设置粘滞位后,只有目录的所有者才能够删除目录中的文件,即使其他人有该目录的写权限也无法执行删除操作。
可以使用chmod的+t选项设置:

$ chmod a+t directory_name

3.4 以递归方式设置文件权限

有时候需要以递归的方式修改当前目录下的所有文件和子目录的权限。chmod的-R选项能够实现这种需求:

$ chmod 777 . -R

选项-R指定以递归的方式修改权限。
我们用.指定当前工作目录,这等同于:

$ chmod 777 "$(pwd)" -R

3.5 以递归的方式设置所有权

用chown命令的-R能够以递归的方式设置所有权:

$ chown user:group . -R

3.6 以不同的身份运行可执行文件(setuid)

**一些可执行文件需要以另一种身份来运行。**例如,http服务器会在系统启动期间由root负责运行,但是该进程应该属于用户httpd。setuid权限允许其他用户以文件所有者的身份来执行文件。
首先将文件的所有权更改为需要执行该文件的用户,然后以该用户的身份登录。运行下面的命令:

$ chmod +s executable_file
# chown root:root executable_file
# chmod +s executable_file
$ ./executable_file

现在,无论是谁发起调用,该文件都是以root用户的身份来执行。
关于setuid的详解

三、将文件设置为不可修改

在所有的Linux文件系统中都可以设置读、写、可执行以及setuid权限。除此之外,扩展文件系统(例如ext2、ext3、ext4)还支持其他属性。其中一种扩展属性就是可以设置不可修改的文件。一旦设置,包括root在内的任何用户都无
法删除该文件,除非撤销其不可修改的属性
。可以利用命令df -T或是通过查看 /etc/mtab文件来确定文件系统的类型。/etc/mtab文件的第一列指定了分区设备路径(例如/dev/sda5),第三列指定了文件系统类型(例如ext3)。

不可修改属性是避免文件被篡改的安全手段之一。/etc/resolv.conf文件就是这样的一个例子。该文件包含了一组DNS服务器列表。DNS服务器负责将域名(例如packtpub.com)转换成IP地址。它通常被设置成你所属ISP的DNS服务器地址。但如果你更喜欢使用第三方的DNS服务器,可以修改/etc/resolv.conf,将其指向所选的服务器。可当下次你再连接到ISP时,/etc/resolv.conf又会恢复到之前的设置。为了避免这种情况,需要将/etc/resolv.conf 设置成不可修改。

3.1 chattr

chattr命令可用于更改扩展属性。它能够将文件设置为不可修改,也可以修改其他属性来调节文件系统同步或压缩率。

3.1.1 使用chatter将文件设置为不可修改

# chattr +i file
# rm file
# rm: cannot remove 'file': Operation not permitted

3.1.2 撤销不可修改属性

chattr -i file

四、批量生成空白文件

4.1 touch

4.1.1 调用touch命令并使用一个不存在的文件名作为参数,创建空白文件

$ touch filename

4.1.2 批量生成不同名字的空白文件

for name in {1..100}.txt
do
	touch $name
done

在上面的代码中,{1…100}会扩展成一个字符串1, 2, 3, 4, 5, 6, 7…100。除了
{1…100}.txt,我们还可以使用其他简写样式,比如 test{1…200}.c、test{a…z}.txt等。

4.1.3 想更改时间戳

 touch -a 只更改文件访问时间。
 touch -m 只更改文件修改时间。
除了将时间戳更改为当前时间,我们还能够指定特定的时间和日期:

$ touch -d "Fri Jun 25 20:50:14 IST 1999" filename

-d使用的日期串不需要是严格的格式。它可以接受多种短格式日期。我们可以忽略具体时间,使用Jan 20, 2010这种格式。

五、查找符号链接及其指向目标

5.1 创建符号链接

$ ln -s target symbolic_link_name

例如:

$ ln -l -s /var/www/ ~/web

这个命令在当前用户的主目录中创建了一个名为Web的符号链接。该链接指向/var/www

5.2 来验证链接是否已建立

$ ls -l web
lrwxrwxrwx 1 slynux slynux 8 2010-06-25 21:34 web -> /var/www

web -> /var/www表明web指向 /var/www。

5.3 打印出当前目录下的符号链接

$ ls -l | grep "^l"

^表示字符串的起始位置。其后的l指定了字符串必须以l开头,
这标识了一个符号链接①。

5.4 打印出当前目录及其子目录下的符号链接

$ find . -type l -print

5.5 使用readlink打印出符号链接所指向的目标路径

$ readlink web
/var/www

五、枚举文件类型统计信息

5.1 枚举文件类型统计信息

5.1.1 打印文件类型信息

$ file filename
$ file /etc/passwd
/etc/passwd: ASCII text

5.1.2 打印不包括文件名在内的文件类型信息

$ file -b filename
ASCII text

5.2 遍历大量文件并收集相关细节的脚本

  1 #!/bin/bash
  2 
  3 if [ $# -ne 1 ];
  4 then
  5         echo "Usage is $0 basepath"
  6         exit
  7 fi
  8 
  9 path=$1
 10 
 11 declare -A statarrary;
 12 
 13 while read line;
 14 do
 15         ftype=`file -b "$line" | cut -d, -f1`
 16         let statarrary["$ftype"]++;
 17 
 18 done < <(find $path -type f -print)
 19 
 20 echo =========File type and coubts=========
 21 
 22 for type in "${!statarrary[@]}";
 23 do
 24         echo $type : ${statarrary["$ftype"]}
 25 done

find命令使用选项-type f返回$path所定义的目录下的文件列表。read命令一次读取一个文件名。当read接收到EOF(文件末尾)时,它返回假,while命令退出。

在while循环中,file命令用于确定文件类型。-b选项只显示出文件类型(不包含文件名)。file命令能够提供很多细节信息,比如图像编码以及分辨率(如果是图像文件的话)。各种细节信息由逗号分隔,例如:

$ file a.out -b
ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not
stripped

我们只需要从上面这些信息中提取ELF 32-bit LSB executable。因此使用-d,指明以逗号作为分隔符,使用-f1选择第一个字段。

<(find $path -type f -print)等同于文件名。只不过它用子进程输出来代替文件名。
注意,第一个<用于输入重定向,第二个<用于将子进程的输出转换成文件名。在两个<之间有一个空格,避免shell将其解释为<<操作符。

${!statarray[@]}用于返回数组的索引列表。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章