成于坚持,败于止步
Comparison
diff, patch
diff: 一个非常灵活的文件比较工具. 这个工具将会以一行接一行的形式来比较目标文件. 在某些应用中, 比如说比较单词词典, 在通过管道将结果传递给diff命令之前, 使用诸如sort和uniq命令来对文件进行过滤将是非常有用的.
diff file-1 file-2 将会输出两个文件中不同的行, 并会通过符号标识出每个不同行所属的文件.
diff命令的--side-by-side选项将会按照左右分隔的形式, 把两个比较中的文件全部输出, 并且会把不同的行标记出来. -c和-u选项也会使得diff命令的输出变得容易解释一些.
还有一些diff命令的变种, 比如sdiff, wdiff, xdiff, 和mgdiff.
如果比较的两个文件是完全一样的话, 那么diff命令会返回0作为退出状态码, 如果不同的话就返回1作为退出码. 这样diff命令就可以用在shell脚本的测试结构中了.
diff命令的一个重要用法就是产生区别文件, 这个文件将用作patch命令的-e选项的参数, -e选项接受ed或ex脚本.
patch: 灵活的版本工具. 给出一个用diff命令产生的区别文件, patch命令可以将一个老版本的包更新为一个新版本的包. 因为你发布一个小的"区别"文件远比重新发布一个大的软件包来的容易得多. 对于频繁更新的Linux内核来说, 使用内核"补丁包"的形式来发布是一种非常好的办法.
patch -p1 <patch-file
上面命令在'patch-file'中取得所有的修改列表, 然后把它们更新到相应的文件中. 那么这个包就被更新为新版本了.
更新内核的方法:
cd /usr/src
gzip -cd patchXX.gz | patch -p0
上面方法使用'patch'来更新内核源文件.
diff也可以递归的比较目录下的所有文件(包含子目录).
使用zdiff来比较gzip文件.
diff3
这是diff命令的扩展版本, 可以同时比较三个文件. 如果成功执行那么这个命令就返回0, 但不幸的是这个命令不给出比较结果的信息.
sdiff
比较和(或)编辑两个文件, 将它们合并到一个输出文件中. 由于这个命令的交互特性, 所以在脚本中很少使用这个命令.
cmp
cmp命令是上边diff命令的一个简单版本. diff命令会报告两个文件的不同之处, 而cmp命令仅仅指出哪些位置有所不同, 不会显示不同之处的具体细节.
就像diff命令那样, 如果两个文件相同的话, cmp将返回0作为退出状态码, 如果不同就返回1. 这样能用在shell脚本的测试结构中了.
看一个实例:在一个脚本中使用cmp命令来比较两个文件
#!/bin/bash ARGS=2 # 脚本需要两个参数. E_BADARGS=65 E_UNREADABLE=66 if [ $# -ne "$ARGS" ] then echo "Usage: `basename $0` file1 file2" exit $E_BADARGS fi if [[ ! -r "$1" || ! -r "$2" ]] then echo "Both files to be compared must exist and be readable." exit $E_UNREADABLE fi cmp $1 $2 &> /dev/null # /dev/null将会禁止"cmp"命令的输出. # cmp -s $1 $2 与上边这句的结果相同("-s"选项是禁止输出(silent)标志) # 感谢Anders Gustavsson指出这点. # # 使用'diff'命令也可以, 比如, diff $1 $2 &> /dev/null if [ $? -eq 0 ] # 测试"cmp"命令的退出状态. then echo "File \"$1\" is identical to file \"$2\"." else echo "File \"$1\" differs from file \"$2\"." fi exit 0结果:
root@ubuntu:~/resource/shell-study/0622-2013# chmod +x test5.sh root@ubuntu:~/resource/shell-study/0622-2013# ./test5.sh test1.sh test2.sh File "test1.sh" differs from file "test2.sh". root@ubuntu:~/resource/shell-study/0622-2013#使用zcmp处理gzip文件.
comm
多功能的文件比较工具. 使用这个命令之前必须先排序.
comm -options first-file second-file
comm file-1 file-2 将会输出3列:
第1列 = 只在file-1中存在的行
第2列 = 只在file-2中存在的行
第3列 = 两边相同的行.
下列选项可以禁止一列或多列的输出.
-1 禁止显示第1列
-2 禁止显示第2列
-3 禁止显示第3列
-12 禁止第1列和第2列, 等等. (就是说选项可以组合)
root@ubuntu:~/resource/shell-study/0622-2013# cat file1 123456 hello 654321 boy root@ubuntu:~/resource/shell-study/0622-2013# cat file2 123456 hi 654321 girl cat root@ubuntu:~/resource/shell-study/0622-2013# comm file1 file2 123456 hello comm: file 1 is not in sorted order 654321 boy hi comm: file 2 is not in sorted order 654321 girl cat root@ubuntu:~/resource/shell-study/0622-2013# comm -1 file1 file2 123456 comm: file 1 is not in sorted order hi comm: file 2 is not in sorted order 654321 girl cat root@ubuntu:~/resource/shell-study/0622-2013# comm -2 file1 file2 123456 hello comm: file 1 is not in sorted order 654321 boy comm: file 2 is not in sorted order root@ubuntu:~/resource/shell-study/0622-2013# comm -12 file1 file2 123456 comm: file 1 is not in sorted order comm: file 2 is not in sorted order root@ubuntu:~/resource/shell-study/0622-2013#Utilities
basename
从文件名中去掉路径信息, 只打印出文件名. 结构basename $0可以让脚本获得它自己的名字, 也就是, 它被调用的名字. 可以用来显示"用法"信息, 比如如果你调用脚本的时候缺少参数, 可以使用如下语句:
echo "Usage: `basename $0` arg1 arg2 ... argn"
dirname
从带路径的文件名字符串中去掉文件名(basename), 只打印出路径信息.
basename和dirname可以操作任意字符串. 它们的参数不一定是一个真正存在的文件, 甚至可以只是一个文件名
#!/bin/bash a=/home/bozo/daily-journal.txt echo "Basename of /home/bozo/daily-journal.txt = `basename $a`" echo "Dirname of /home/bozo/daily-journal.txt = `dirname $a`" echo echo "My own home is `basename ~/`." # `basename ~` 也可以. echo "The home of my home is `dirname ~/`." # `dirname ~` 也可以. exit 0结果:
root@ubuntu:~/resource/shell-study/0622-2013# chmod +x test6.sh root@ubuntu:~/resource/shell-study/0622-2013# ./test6.sh Basename of /home/bozo/daily-journal.txt = daily-journal.txt Dirname of /home/bozo/daily-journal.txt = /home/bozo My own home is root. The home of my home is /. root@ubuntu:~/resource/shell-study/0622-2013#
split, csplit
将一个文件分割为几个小段的工具. 这些命令通常会将大的文件分割, 然后备份到软盘上, 或者是为了将大文件切成合适的尺寸, 然后用email上传.csplit命令会根据上下文来切割文件, 切割的位置将会发生在模式匹配的地方.
sum, cksum, md5sum, sha1sum
这些都是用来产生checksum的工具. checksum是对文件的内容进行数学计算而得到的, 它的目的是用来检验文件的完整性, 出于安全目的一个脚本可能会有一个checksum列表, 这样可以确保关键系统文件的内容不会被修改或损坏. 对于需要安全性的应用来说, 应该使用md5sum (message digest 5 checksum)命令, 或者使用更好更新的sha1sum命令(安全Hash算法).
root@ubuntu:~/resource/shell-study/0622-2013# cksum /boot/ abi-2.6.32-21-generic initrd.img-2.6.32-21-generic vmcoreinfo-2.6.32-21-generic config-2.6.32-21-generic memtest86+.bin vmlinuz-2.6.32-21-generic grub/ System.map-2.6.32-21-generic root@ubuntu:~/resource/shell-study/0622-2013# cksum /boot/vm vmcoreinfo-2.6.32-21-generic vmlinuz-2.6.32-21-generic root@ubuntu:~/resource/shell-study/0622-2013# cksum /boot/vmlinuz-2.6.32-21-generic 3690579176 4029792 /boot/vmlinuz-2.6.32-21-generic root@ubuntu:~/resource/shell-study/0622-2013# echo -n "Top Sercret" | cksum 2021153305 11 root@ubuntu:~/resource/shell-study/0622-2013# md5sum /boot/vmlinuz-2.6.32-21-generic 1c0d4864792ec0bb7660f303f805a2fe /boot/vmlinuz-2.6.32-21-generic root@ubuntu:~/resource/shell-study/0622-2013# echo -n "Top Sercret" | md5sum cc20b742f8db0c240be6ad0b846d8cb8 - root@ubuntu:~/resource/shell-study/0622-2013#
一个实例:检查文件完整性
#!/bin/bash # 检查一个给定目录下的文件是否被改动了. E_DIR_NOMATCH=70 E_BAD_DBFILE=71 dbfile=File_record.md5 # 存储记录的文件名(数据库文件). set_up_database () { echo ""$directory"" > "$dbfile" # 把目录名写到文件的第一行. md5sum "$directory"/* >> "$dbfile" # 在文件中附上md5 checksum和filename. } check_database () { local n=0 local filename local checksum # ------------------------------------------- # # 这个文件检查其实是不必要的, #+ 但是能更安全一些. if [ ! -r "$dbfile" ] then echo "Unable to read checksum database file!" exit $E_BAD_DBFILE fi # ------------------------------------------- # while read record[n] do directory_checked="${record[0]}" if [ "$directory_checked" != "$directory" ] then echo "Directories do not match up!" # 换个目录试一下. exit $E_DIR_NOMATCH fi if [ "$n" -gt 0 ] # 不是目录名. then filename[n]=$( echo ${record[$n]} | awk '{ print $2 }' ) # md5sum向后写记录, #+ 先写checksum, 然后写filename. checksum[n]=$( md5sum "${filename[n]}" ) if [ "${record[n]}" = "${checksum[n]}" ] then echo "${filename[n]} unchanged." elif [ "`basename ${filename[n]}`" != "$dbfile" ] # 跳过checksum数据库文件, #+ 因为在每次调用脚本它都会被修改. # --- # 这不幸的意味着当我们在$PWD中运行这个脚本时侯, #+ 篡改这个checksum数 #+ 据库文件将不会被检测出来. # 练习: 修正这个问题. then echo "${filename[n]} : CHECKSUM ERROR!" # 从上次的检查之后, 文件已经被修改. fi fi let "n+=1" done <"$dbfile" # 从checksum数据库文件中读. } # =================================================== # # main () if [ -z "$1" ] then directory="$PWD" # 如果没指定参数的话, else #+ 那么就使用当前的工作目录. directory="$1" fi #clear # 清屏. echo " Running file integrity check on $directory" echo # ------------------------------------------------------------------ # if [ ! -r "$dbfile" ] # 是否需要建立数据库文件? then echo "Setting up database file, \""$directory"/"$dbfile"\"."; echo set_up_database fi # ------------------------------------------------------------------ # check_database # 调用主要处理函数. echo # 你可能想把这个脚本的输出重定向到文件中, #+ 尤其在这个目录中有很多文件的时候. exit 0结果:
root@ubuntu:~/resource/shell-study/0622-2013# ls file1 file2 test1.sh test2.sh test3.sh test4.sh test5.sh test6.sh test7.sh root@ubuntu:~/resource/shell-study/0622-2013# ./test7.sh Running file integrity check on /root/resource/shell-study/0622-2013 Setting up database file, "/root/resource/shell-study/0622-2013/File_record.md5". /root/resource/shell-study/0622-2013/file1 unchanged. /root/resource/shell-study/0622-2013/file2 unchanged. /root/resource/shell-study/0622-2013/test1.sh unchanged. /root/resource/shell-study/0622-2013/test2.sh unchanged. /root/resource/shell-study/0622-2013/test3.sh unchanged. /root/resource/shell-study/0622-2013/test4.sh unchanged. /root/resource/shell-study/0622-2013/test5.sh unchanged. /root/resource/shell-study/0622-2013/test6.sh unchanged. /root/resource/shell-study/0622-2013/test7.sh unchanged. root@ubuntu:~/resource/shell-study/0622-2013# vi test1.sh root@ubuntu:~/resource/shell-study/0622-2013# ./test7.sh Running file integrity check on /root/resource/shell-study/0622-2013 /root/resource/shell-study/0622-2013/file1 unchanged. /root/resource/shell-study/0622-2013/file2 unchanged. /root/resource/shell-study/0622-2013/test1.sh : CHECKSUM ERROR! /root/resource/shell-study/0622-2013/test2.sh unchanged. /root/resource/shell-study/0622-2013/test3.sh unchanged. /root/resource/shell-study/0622-2013/test4.sh unchanged. /root/resource/shell-study/0622-2013/test5.sh unchanged. /root/resource/shell-study/0622-2013/test6.sh unchanged. /root/resource/shell-study/0622-2013/test7.sh unchanged. root@ubuntu:~/resource/shell-study/0622-2013# ls file1 file2 File_record.md5 test1.sh test2.sh test3.sh test4.sh test5.sh test6.sh test7.sh root@ubuntu:~/resource/shell-study/0622-2013#
root@ubuntu:~/resource/shell-study/0622-2013# cat File_record.md5 /root/resource/shell-study/0622-2013 706ff1928dec96f2bf6e4ddf61db5856 /root/resource/shell-study/0622-2013/file1 c4396191d66ed8992ad4bec7579eb87b /root/resource/shell-study/0622-2013/file2 1204c3876839d879b6fa70c0c6b22394 /root/resource/shell-study/0622-2013/File_record.md5 2ea9a2e6384be12ac0dcdadbce144a3a /root/resource/shell-study/0622-2013/test1.sh b1dd05cfb334ee0e8a56fbcbd4e61f09 /root/resource/shell-study/0622-2013/test2.sh 329c96ec93b6ac40c2f5cdc355ae064f /root/resource/shell-study/0622-2013/test3.sh a474a06fcf0983153f256db619055643 /root/resource/shell-study/0622-2013/test4.sh 0c26226596e42d1cc5f6db7b0c08667a /root/resource/shell-study/0622-2013/test5.sh 609b3360144ed918dd093b7b5b17184c /root/resource/shell-study/0622-2013/test6.sh ff08054c16d2e70cce93437e039c5f6a /root/resource/shell-study/0622-2013/test7.sh root@ubuntu:~/resource/shell-study/0622-2013#
shred
用随机字符填充文件, 使得文件无法恢复, 这样就可以保证文件安全的被删除, 但是使用这个命令是一种更优雅更彻底的方法.其实即使使用了shred命令, 高级的辨别技术也还是能够恢复文件的内容.O(∩_∩)O~
root@ubuntu:~/resource/shell-study/0622-2013# cat file1 123456 hello 654321 boy root@ubuntu:~/resource/shell-study/0622-2013# shred file1 root@ubuntu:~/resource/shell-study/0622-2013# cat file1 ��W��|�Y'���4�����D�v ���Up��JE��]E���m'mqM{D�9��;�D5�+�A�3�&f"�l|�@�`���P`_�X��t�i�j�t��,�K��a�p�����@�b��}��'��e[��1���ݯP�5M����%_#��9�)����9(�:8Yo>��J!�$.��Z�\�� root@ubuntu:~/resource/shell-study/0622-2013#看到产生的一堆随机字符,这样之后然后再删除文件达到上面说的目的
编码和解码
uuencode
这个工具用来把二进制文件编码成ASCII字符串, 这个工具适用于编码e-mail消息体, 或者新闻组消息.
uudecode
这个工具用来把uuencode后的ASCII字符串恢复为二进制文件.
一个实例:Uudecode编码后的文件
#!/bin/bash # 在当前目录下用Uudecode解码所有用uuencode编码的文件. lines=35 # 允许读头部的35行(范围很宽). for File in * # 测试所有$PWD下的文件. do search1=`head -$lines $File | grep begin | wc -w` search2=`tail -$lines $File | grep end | wc -w` # 用Uuencode编码过的文件在文件开始的地方都有个"begin", #+ 在文件结尾的地方都有"end". if [ "$search1" -gt 0 ] then if [ "$search2" -gt 0 ] then echo "uudecoding - $File -" uudecode $File fi fi done # 小心不要让这个脚本运行自己, #+ 因为它也会把自身也认为是一个经过uuencode编码过的文件, #+ 这都是因为这个脚本自身也包含"begin"和"end". exit 0
mimencode, mmencode
mimencode和mmencode命令用来处理多媒体编码的email附件. 虽然mail用户代理(比如pine或kmail)通常情况下都会自动处理, 但是这些特定的工具允许从命令行或shell脚本中来手动操作这些附件.
crypt
这个工具曾经是标准的UNIX文件加密工具. 政府由于政策上的动机规定禁止加密软件的输出, 这样导致了crypt命令从UNIX世界消失, 并且在大多数的Linux发行版中也没有这个命令. 幸运的是, 程序员们想出了一些替代它的方法, 在这些方法中有作者自己的cruft
Miscellaneous
mktemp
使用一个"唯一"的文件名来创建一个临时文件.如果不带参数的在命令行下调用这个命令时, 将会在/tmp目录下产生一个零长度的文件.
root@ubuntu:~/resource/shell-study/0622-2013# mktemp /tmp/tmp.N4A1vdapbN root@ubuntu:~/resource/shell-study/0622-2013# ls -l /tmp/tmp.N4A1vdapbN -rw------- 1 root root 0 2013-06-21 19:42 /tmp/tmp.N4A1vdapbN root@ubuntu:~/resource/shell-study/0622-2013#
root@ubuntu:~/resource/shell-study/0622-2013# mktemp file.XXXXXXXX file.EfieeYhy root@ubuntu:~/resource/shell-study/0622-2013#在这个临时的文件名中 至少需要8个占位符. 如果没有指定临时文件的文件名, 那么默认就是"tmp.XXXXXXXXXX",上面生成的tmp.N4A1vdapbN也验证了这一点
make
build(建立)和compile(编译)二进制包的工具. 当源文件被增加或修改时就会触发一些操作, 这个工具用来控制这些操作.
make命令会检查Makefile, makefile是文件的依赖和操作列表.
install
特殊目的的文件拷贝命令, 与cp命令相似, 但是具有设置拷贝文件的权限和属性的能力. 这个命令看起来是为了安装软件包所定制的, 而且就其本身而言, 这个命令经常出现在Makefiles中(在make install : 区域中). 在安装脚本中也会看到这个命令的使用.
dos2unix
这个工具是由Benjamin Lin及其同事共同编写的, 目的是将DOS格式的文本文件(以CR-LF为行结束符)转换为UNIX格式(以LF为行结束符), 反过来也一样.
ptx
ptx [targetfile]命令将输出目标文件的序列改变索引(交叉引用列表). 如果必要的话, 这个命令可以在管道中进行更深层次的过滤和格式化.
more, less
分页显示文本文件或stdout, 一次一屏. 可以用来过滤stdout的输出 . . . 或过滤一个脚本的输出.
more命令的一个有趣的应用就是测试一个命令序列的执行, 这样做的目的是避免可能发生的糟糕的结果.
root@ubuntu:~/resource/shell-study/0622-2013# ls -l /usr/bin/ ...... -rwxr-xr-x 1 root root 76060 2010-02-15 09:40 zipnote -rwxr-xr-x 1 root root 80156 2010-02-15 09:40 zipsplit -rwxr-xr-x 1 root root 57588 2010-03-25 01:12 zjsdecode -rwxr-xr-x 1 root root 88168 2010-03-02 02:31 zsoelim ...... root@ubuntu:~/resource/shell-study/0622-2013# ls -l /usr/bin/ | awk '{print $6}' | more 2010-03-04 2012-11-30 2010-04-16 2010-04-23 2012-11-30 2010-03-28 2010-04-23 2010-01-29 2010-04-14 2010-03-22 2010-04-18 2010-03-29 2010-03-28 2010-03-28 2010-03-28 2009-11-13 2009-11-26 2010-03-28 2010-03-28 --More--点击空格键翻页,q退出
先到这里了,O(∩_∩)O~
我的专栏地址:http://blog.csdn.net/column/details/shell-daily-study.html
待续。。。。