filearchiv.html
来自「BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版」· HTML 代码 · 共 3,680 行 · 第 1/5 页
HTML
3,680 行
>命令是上边<BCLASS="COMMAND">diff</B>命令的一个简单版本. <BCLASS="COMMAND">diff</B>命令会报告两个文件的不同之处, 而<BCLASS="COMMAND">cmp</B>命令仅仅指出哪些位置有所不同, 不会显示不同之处的具体细节. </P><DIVCLASS="NOTE"><P></P><TABLECLASS="NOTE"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/note.gif"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>就像<BCLASS="COMMAND">diff</B>命令那样, 如果两个文件相同的话, <BCLASS="COMMAND">cmp</B>将返回0作为退出状态码, 如果不同就返回1. 这样能用在shell脚本的测试结构中了. </P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="FILECOMP"></A><P><B>例子 12-32. 在一个脚本中使用<BCLASS="COMMAND">cmp</B>命令来比较两个文件. </B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 ARGS=2 # 脚本需要两个参数. 4 E_BADARGS=65 5 E_UNREADABLE=66 6 7 if [ $# -ne "$ARGS" ] 8 then 9 echo "Usage: `basename $0` file1 file2" 10 exit $E_BADARGS 11 fi 12 13 if [[ ! -r "$1" || ! -r "$2" ]] 14 then 15 echo "Both files to be compared must exist and be readable." 16 exit $E_UNREADABLE 17 fi 18 19 cmp $1 $2 &> /dev/null # /dev/null将会禁止"cmp"命令的输出. 20 # cmp -s $1 $2 与上边这句的结果相同("-s"选项是禁止输出(silent)标志) 21 # 感谢Anders Gustavsson指出这点. 22 # 23 # 使用'diff'命令也可以, 比如, diff $1 $2 &> /dev/null 24 25 if [ $? -eq 0 ] # 测试"cmp"命令的退出状态. 26 then 27 echo "File \"$1\" is identical to file \"$2\"." 28 else 29 echo "File \"$1\" differs from file \"$2\"." 30 fi 31 32 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="TIP"><P></P><TABLECLASS="TIP"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/tip.gif"HSPACE="5"ALT="Tip"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>使用<BCLASS="COMMAND">zcmp</B>处理<EM>gzip</EM>文件. </P></TD></TR></TABLE></DIV></DD><DT><BCLASS="COMMAND">comm</B></DT><DD><P>多功能的文件比较工具. 使用这个命令之前必须先排序. </P><P><BCLASS="COMMAND">comm <TTCLASS="REPLACEABLE"><I>-options</I></TT> <TTCLASS="REPLACEABLE"><I>first-file</I></TT> <TTCLASS="REPLACEABLE"><I>second-file</I></TT></B></P><P><KBDCLASS="USERINPUT">comm file-1 file-2</KBD> 将会输出3列: <P></P><UL><LI><P>第1列 = 只在<TTCLASS="FILENAME">file-1</TT>中存在的行</P></LI><LI><P>第2列 = 只在<TTCLASS="FILENAME">file-2</TT>中存在的行</P></LI><LI><P>第3列 = 两边相同的行. </P></LI></UL></P><P>下列选项可以禁止一列或多列的输出. <P></P><UL><LI><P><CODECLASS="OPTION">-1</CODE> 禁止显示第<TTCLASS="LITERAL">1</TT>列 (译者: 在File1中的行)</P></LI><LI><P><CODECLASS="OPTION">-2</CODE> 禁止显示第<TTCLASS="LITERAL">2</TT>列 (译者: 在File2中的行)</P></LI><LI><P><CODECLASS="OPTION">-3</CODE> 禁止显示第<TTCLASS="LITERAL">3</TT>列 (译者: 在File3中的行)</P></LI><LI><P><CODECLASS="OPTION">-12</CODE> 禁止第<TTCLASS="LITERAL">1</TT>列和第<TTCLASS="LITERAL">2</TT>列, 等等. (译者: 就是说选项可以组合)</P></LI></UL> </P></DD></DL></DIV><P></P><DIVCLASS="VARIABLELIST"><P><B><ANAME="FAUTILS1"></A>Utilities</B></P><DL><DT><BCLASS="COMMAND">basename</B></DT><DD><P>从文件名中去掉路径信息, 只打印出文件名. 结构<KBDCLASS="USERINPUT">basename $0</KBD>可以让脚本获得它自己的名字, 也就是, 它被调用的名字. 可以用来显示<SPANCLASS="QUOTE">"用法"</SPAN>信息, 比如如果你调用脚本的时候缺少参数, 可以使用如下语句: <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 echo "Usage: `basename $0` arg1 arg2 ... argn"</PRE></FONT></TD></TR></TABLE> </P></DD><DT><BCLASS="COMMAND">dirname</B></DT><DD><P>从带路径的文件名字符串中去掉文件名(<BCLASS="COMMAND">basename</B>), 只打印出路径信息. </P><DIVCLASS="NOTE"><P></P><TABLECLASS="NOTE"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/note.gif"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P><BCLASS="COMMAND">basename</B>和<BCLASS="COMMAND">dirname</B>可以操作任意字符串. 它们的参数不一定是一个真正存在的文件, 甚至可以不是一个文件名. (请参考<AHREF="contributed-scripts.html#DAYSBETWEEN">例子 A-7</A>). </P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="EX35"></A><P><B>例子 12-33. <BCLASS="COMMAND">basename</B>和<BCLASS="COMMAND">dirname</B></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 a=/home/bozo/daily-journal.txt 4 5 echo "Basename of /home/bozo/daily-journal.txt = `basename $a`" 6 echo "Dirname of /home/bozo/daily-journal.txt = `dirname $a`" 7 echo 8 echo "My own home is `basename ~/`." # `basename ~` 也可以. 9 echo "The home of my home is `dirname ~/`." # `dirname ~` 也可以. 10 11 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV></DD><DT><BCLASS="COMMAND">split</B>, <BCLASS="COMMAND">csplit</B></DT><DD><P>将一个文件分割为几个小段的工具. 这些命令通常会将大的文件分割, 然后备份到软盘上, 或者是为了将大文件切成合适的尺寸, 然后用email上传. </P><P><BCLASS="COMMAND">csplit</B>命令会根据<EM>上下文</EM>来切割文件, 切割的位置将会发生在模式匹配的地方. </P></DD><DT><BCLASS="COMMAND">sum</B>, <BCLASS="COMMAND">cksum</B>, <ANAME="MD5SUMREF"></A><BCLASS="COMMAND">md5sum</B>, <BCLASS="COMMAND">sha1sum</B></DT><DD><P>这些都是用来产生checksum的工具. <EM>checksum</EM>是对文件的内容进行数学计算而得到的, 它的目的是用来检验文件的完整性, 出于安全目的一个脚本可能会有一个checksum列表, 这样可以确保关键系统文件的内容不会被修改或损坏. 对于需要安全性的应用来说, 应该使用<BCLASS="COMMAND">md5sum</B> (<BCLASS="COMMAND">m</B>essage <BCLASS="COMMAND">d</B>igest <BCLASS="COMMAND">5</B> check<BCLASS="COMMAND">sum</B>)命令, 或者使用更好更新的<BCLASS="COMMAND">sha1sum</B>命令(安全Hash算法). </P><P> <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">cksum /boot/vmlinuz</KBD><SAMPCLASS="COMPUTEROUTPUT">1670054224 804083 /boot/vmlinuz</SAMP><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">echo -n "Top Secret" | cksum</KBD><SAMPCLASS="COMPUTEROUTPUT">3391003827 10</SAMP><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">md5sum /boot/vmlinuz</KBD><SAMPCLASS="COMPUTEROUTPUT">0f43eccea8f09e0a0b2b5cf1dcf333ba /boot/vmlinuz</SAMP><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">echo -n "Top Secret" | md5sum</KBD><SAMPCLASS="COMPUTEROUTPUT">8babc97a6f62a4649716f4df8d61728f -</SAMP> </PRE></FONT></TD></TR></TABLE> </P><DIVCLASS="NOTE"><P></P><TABLECLASS="NOTE"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/note.gif"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P><BCLASS="COMMAND">cksum</B>将会显示目标尺寸(以字节为单位), 目标可以是<TTCLASS="FILENAME">stdout</TT>, 也可以是文件. </P><P><BCLASS="COMMAND">md5sum</B>和<BCLASS="COMMAND">sha1sum</B>命令在它们收到来自于<TTCLASS="FILENAME">stdout</TT>的输入的时候, 显示一个<AHREF="special-chars.html#DASHREF2">dash</A>. </P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="FILEINTEGRITY"></A><P><B>例子 12-34. 检查文件完整性</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # file-integrity.sh: 检查一个给定目录下的文件 3 # 是否被改动了. 4 5 E_DIR_NOMATCH=70 6 E_BAD_DBFILE=71 7 8 dbfile=File_record.md5 9 # 存储记录的文件名(数据库文件). 10 11 12 set_up_database () 13 { 14 echo ""$directory"" > "$dbfile" 15 # 把目录名写到文件的第一行. 16 md5sum "$directory"/* >> "$dbfile" 17 # 在文件中附上md5 checksum和filename. 18 } 19 20 check_database () 21 { 22 local n=0 23 local filename 24 local checksum 25 26 # ------------------------------------------- # 27 # 这个文件检查其实是不必要的, 28 #+ 但是能更安全一些. 29 30 if [ ! -r "$dbfile" ] 31 then 32 echo "Unable to read checksum database file!" 33 exit $E_BAD_DBFILE 34 fi 35 # ------------------------------------------- # 36 37 while read record[n] 38 do 39 40 directory_checked="${record[0]}" 41 if [ "$directory_checked" != "$directory" ] 42 then 43 echo "Directories do not match up!" 44 # 换个目录试一下. 45 exit $E_DIR_NOMATCH 46 fi 47 48 if [ "$n" -gt 0 ] # 不是目录名. 49 then 50 filename[n]=$( echo ${record[$n]} | awk '{ print $2 }' ) 51 # md5sum向后写记录, 52 #+ 先写checksum, 然后写filename. 53 checksum[n]=$( md5sum "${filename[n]}" ) 54 55 56 if [ "${record[n]}" = "${checksum[n]}" ] 57 then 58 echo "${filename[n]} unchanged." 59 60 elif [ "`basename ${filename[n]}`" != "$dbfile" ] 61 # 跳过checksum数据库文件, 62 #+ 因为在每次调用脚本它都会被修改. 63 # --- 64 # 这不幸的意味着当我们在$PWD中运行这个脚本时侯, 65 #+ 篡改这个checksum数 66 #+ 据库文件将不会被检测出来. 67 # 练习: 修正这个问题. 68 then 69 echo "${filename[n]} : CHECKSUM ERROR!" 70 # 从上次的检查之后, 文件已经被修改. 71 fi 72 73 fi 74 75 76 77 let "n+=1" 78 done <"$dbfile" # 从checksum数据库文件中读. 79 80 } 81 82 # =================================================== # 83 # main () 84 85 if [ -z "$1" ] 86 then 87 directory="$PWD" # 如果没指定参数的话, 88 else #+ 那么就使用当前的工作目录. 89 directory="$1" 90 fi 91 92 clear # 清屏. 93 echo " Running file integrity check on $directory" 94 echo 95 96 # ------------------------------------------------------------------ # 97 if [ ! -r "$dbfile" ] # 是否需要建立数据库文件? 98 then 99 echo "Setting up database file, \""$directory"/"$dbfile"\"."; echo100 set_up_database101 fi 102 # ------------------------------------------------------------------ #103 104 check_database # 调用主要处理函数. 105 106 echo 107 108 # 你可能想把这个脚本的输出重定向到文件中, 109 #+ 尤其在这个目录中有很多文件的时候. 110 111 exit 0112 113 # 如果要对数量非常多的文件做完整性检查, 114 #+ 可以考虑一下"Tripwire"包,115 #+ http://sourceforge.net/projects/tripwire/.116 </PRE></FONT></TD></TR></TABLE><HR></DIV><P>请参考<AHREF="contributed-scripts.html#DIRECTORYINFO">例子 A-19</A>和<AHREF="colorizing.html#HORSERACE">例子 33-14</A>, 这两个例子展示了<BCLASS="COMMAND">md5sum</B>命令的用法. </P><DIVCLASS="NOTE"><P></P
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?