当前位置: 首页 > 文档资料 > Shell 中文文档 >

Chapter 12. 外部过滤器,程序和命令

优质
小牛编辑
121浏览
2023-12-01

标准的 UNIX 命令使得 shell 脚本更加灵活.通过简单的编程结构把shell指令和系统命令结合起来,这才是脚本能力的所在.

新手必须要掌握的初级命令

ls

基本的列出所有文件的命令.但是往往就是因为这个命令太简单,所以我们总是低估它.比如,用 -R 选项,这是递归选项,ls 将会以目录树的形式列出所有文件, 另一个很有用的选项是 -S ,将会按照文件尺寸列出所有文件,-t, 将会按照修改时间来列出文件,-i 选项会显示文件的inode(见 Example 12-4).

Example 12-1. 使用ls命令来创建一个烧录CDR的内容列表

   1 #!/bin/bash
   2 # ex40.sh (burn-cd.sh)
   3 # 自动刻录CDR的脚本.
   4
   5
   6 SPEED=2          # 如果你的硬件支持的话,你可以选用更高的速度.
   7 IMAGEFILE=cdimage.iso
   8 CONTENTSFILE=contents
   9 DEVICE=cdrom
  10 # DEVICE="0,0"     为了使用老版本的CDR
  11 DEFAULTDIR=/opt  # 这是包含需要被刻录内容的目录.
  12                  # 必须保证目录存在.
  13                  # 小练习: 测试一下目录是否存在.
  14
  15 # Uses Joerg Schilling's "cdrecord" package:
  15 # 使用 Joerg Schilling 的 "cdrecord"包:
  16 # http://www.fokus.fhg.de/usr/schilling/cdrecord.html
  17
  18 #  如果一般用户调用这个脚本的话,可能需要root身份
  19 #+ chmod u+s /usr/bin/cdrecord
  20 #  当然, 这会产生安全漏洞, 虽然这是一个比较小的安全漏洞.
  21
  22 if [ -z "$1" ]
  23 then
  24   IMAGE_DIRECTORY=$DEFAULTDIR
  25   # 如果命令行没指定的话, 那么这个就是默认目录.
  26 else
  27     IMAGE_DIRECTORY=$1
  28 fi
  29
  30 # 创建一个内容列表文件.
  31 ls -lRF $IMAGE_DIRECTORY > $IMAGE_DIRECTORY/$CONTENTSFILE
  32 #  "l" 选项将给出一个"长"文件列表.
  33 #  "R" 选项将使这个列表递归.
  34 #  "F" 选项将标记出文件类型 (比如: 目录是以 /结尾, 而可执行文件以 *结尾).
  35 echo "Creating table of contents."
  36
  37 # 在烧录到CDR之前创建一个镜像文件.
  38 mkisofs -r -o $IMAGEFILE $IMAGE_DIRECTORY
  39 echo "Creating ISO9660 file system image ($IMAGEFILE)."
  40
  41 # 烧录CDR.
  42 echo "Burning the disk."
  43 echo "Please be patient, this will take a while."
  44 cdrecord -v -isosize speed=$SPEED dev=$DEVICE $IMAGEFILE
  45
  46 exit $?
cat, tac

cat, 是单词 concatenate的缩写,把文件的内容输出到stdout. 当与重定向操作符 (>或>>)结合使用时, 一般都是用来将多个文件连接起来.

   1 # Uses of 'cat'
   2 cat filename                          # 打印出文件内容.
   3
   4 cat file.1 file.2 file.3 > file.123   # 把3个文件连接到一个文件中.

cat命令的 -n 选项是为了在目标文件中的所有行前边插入行号. -b选项 与 -n 选项一样, 区别是不对空行进行编号. -v 选项可以使用 ^ 标记法 来echo 出不可打印字符.-s选项可以把多个空行压缩成一个空行.

Example 12-25Example 12-21.

 

在一个 管道中, 可能有一种把stdin 重定向到一个文件中的更有效的办法, 这种方法比cat文件的方法更有效率.

   1 cat filename | tr a-z A-Z
   2
   3 tr a-z A-Z < filename   #  效果相同,但是处理更少,
   4                         #+ 并且连管道都省掉了.

tac命令, 就是cat的反转, 将从文件的结尾列出文件.

rev

把每一行中的内容反转, 并且输出到stdout上. 这个命令与 tac命令的效果是不同的, 因为它并不反转行序, 而是把每行的内容反转.

 
bash$ 


cat file1.txt

 
This is line 1.
 This is line 2.

bash$ tac file1.txtThis is line 2.This is line 1.

bash$ rev file1.txt.1 enil si sihT.2 enil si sihT

cp

这是文件拷贝命令. cp file1file2file1 拷贝到 file2, 如果存在file2的话,那 file2 将被覆盖 (见 Example 12-6).

 

特别有用的选项就是 -a归档 选项 (为了copy一个完整的目录树), -u是更新选项,和 -r-R递归选项.

   1 cp -u source_dir/* dest_dir
   2 #  "Synchronize" dest_dir to source_dir把源目录"同步"到目标目录上,
   3 #+  也就是拷贝所有更新的文件和之前不存在的文件.
mv

这是文件移动命令. 它等价于 cprm命令的组合. 它可以把多个文件移动到目录中,甚至将目录重命名. 想查看 mv在脚本中使用的例子,见 Example 9-18Example A-2.

 

当使用非交互脚本时,可以使用mv 的-f(强制) 选项来避免用户的输入.

当一个目录被移动到一个已存在的目录时,那么它将成为目标目录的子目录.

 
bash$ 


mv source_directory target_directory

bash$ ls -lF target_directorytotal 1drwxrwxr-x 2 bozo bozo 1024 May 28 19:20 source_directory/

rm

删除(清除)一个或多个文件. -f选项将强制删除文件,即使这个文件是只读的.并且可以用来避免用户输入(在非交互脚本中使用).

 

rm将无法删除以破折号开头的文件.

 
bash$ 


rm -badname

 
rm: invalid option -- b
 Try `rm --help' for more information.

解决这个问题的一个方法就是在要删除的文件的前边加上"./".

 
bash$ 


rm ./-badname

另一种解决的方法是 在文件名前边加上 " -- ".

 
bash$ 


rm -- -badname

 

当使用递归参数-r时, rm 命令将会删除整个目录树.如果不慎使用 rm -rf *那整个目录树就真的完了.

rmdir

删除目录. 但是只有这个目录中没有文件 -- 当然会包含不可见的点文件

chmod

修改一个现存文件的属性 (见 Example 11-12).

   1 chmod +x filename
   2 # 使得文件filename对所有用户都可执行.
   3
   4 chmod u+s filename
   5 # 设置"filename"文件的"suid"位.
   6 # 这样一般用户就可以执行"filename", 他将拥有和文件宿主相同的权限.
   7 # (这并不适用于shell 脚本)
   1 chmod 644 filename
   2 # Makes "filename" readable/writable to owner, readable to
   3 # 设置文件宿主的 r/w 权限,并对一般用户
   3 # 设置读权限.
   4 # (8进制模式).

   1 chmod 1777 directory-name
   2 # 对这个目录设置r/w 和可执行权限, 并开放给所有人.
   3 # 同时设置 "粘贴位".
   4 # 这意味着, 只有目录宿主,
   5 # 文件宿主, 当然, 还有root
   6 # 可以删除这个目录中的任何特定的文件.
chattr

修改文件属性. 这个命令与上边的chmod命令相类似, 但是有不同的选项和不同的调用语法, 并且这个命令只能工作在ext2文件系统中.

chattr命令的一个特别有趣的选项是i. chattr +ifilename将使得这个文件被标记为永远不变. 这个文件将不能被修改, 连接, 或删除, 即使是root也不行. 这个文件属性只能被root设置和删除. 类似的, a 选项将会把文件标记为只能追加数据.

 
root# 


chattr +i file1.txt

root# rm file1.txt

rm: remove write-protected regular file `file1.txt'? yrm: cannot remove `file1.txt': Operation not permitted

如果文件设置了s(安全)属性, 那么当这个文件被删除时,这个文件所在磁盘的块将全部被0填充.

如果文件设置了u(不可删除)属性, 那么当这个文件被删除后, 这个文件的内容还可以被恢复(不可删除).

如果文件设置了c(压缩)属性, 那么当这个文件在进行写操作时,它将自动被压缩,并且在读的时候, 自动解压.

使用命令chattrdo设置的属性, 将不会显示在文件列表中(ls -l).

ln

创建文件链接, 前提是这个文件是存在的. "链接"就是一个文件的引用, 也就是这个文件的另一个名字. ln命令允许对同一个文件引用多个链接,并且是避免混淆的一个很好的方法 (见 Example 4-6).

ln对于文件来说只不过是创建了一个引用, 一个指针而已, 因为创建出来的连接文件只有几个字节.

绝大多数使用ln命令时使用是 -s 选项, 可以称为符号链接, 或软链接.使用 -s 选项的一个优点是它可以穿越文件系统来链接目录.

关于使用这个命令的语法还是有点小技巧的. 比如:ln -s oldfile newfile将对老文件产生一个新的文件链接.

如果之前就存在newfile的话, 那么将会产生一个错误消息.

使用链接中的哪种类型?

就像 John Macdonald 解释的那样:

不论是那种类型的链接, 都提供了一种双向引用的手段 -- 也就是说, 不管你用文件的那个名字对文件内容进行修改, 你修改的效果都即会反映到原始名字的文件, 也会反映到链接名字的文件.当你工作在更高层次的时候, 才会发生软硬链接的不同. 硬链接的优点是, 原始文件与链接文件之间是相互独立的 -- 如果你删除或者重命名老文件, 那么这种操作将不会影响硬链接的文件, 硬链接的文件讲还是原来文件的内容. 然而如果你使用软链接的, 当你把老文件删除或重命名后, 软链接将再也找不到原来文件的内容了. 而软链接的优点是它可以跨越文件系统(因为它只不过是文件名的一个引用, 而并不是真正的数据). 与硬链接的另一个不同是, 一个符号链接可以指向一个目录.

 

链接给出了一种可以用多个名字来调用脚本的能力(当然这也适用于任何可执行的类型), 并且脚本的行为将依赖于脚本是如何被调用的.

Example 12-2. Hello or Good-bye

   1 #!/bin/bash
   2 # hello.sh: 显示"hello" 还是 "goodbye"
   3 #+          依赖于脚本是如何被调用的.
   4
   5 # 在当前目录下($PWD)为这个脚本创建一个链接:
   6 #    ln -s hello.sh goodbye
   7 # 现在, 通过如下两种方法来调用这个脚本:
   8 # ./hello.sh
   9 # ./goodbye
  10
  11
  12 HELLO_CALL=65
  13 GOODBYE_CALL=66
  14
  15 if [ $0 = "./goodbye" ]
  16 then
  17   echo "Good-bye!"
  18   # 当然, 在这里你也可以添加一些其他的 goodbye类型的命令.Some other goodbye-type commands, as appropriate.
  19   exit $GOODBYE_CALL
  20 fi
  21
  22 echo "Hello!"
  23 # 当然, 在这里你也可以添加一些其他的 hello类型的命令.
  24 exit $HELLO_CALL
man, info

These 这两个命令用来查看系统命令或安装工具的手册和信息.当两者都可用时,info页一般比 man也会包含更多的细节描述.

注意事项:

Dotfiles就是文件名以"."开头的文件, 比如~/.Xdefaults. 这样的文件在一般的 ls命令使用中将不会被显示出来 (当然 ls -a将会显示它们), 并且它们也不会被一个意外的rm -rf *删除. 在用户的home目录中,Dotfiles一般被用来当作安装和配置文件.