天天看点

《linux Shell 脚本攻略》进阶学习(第二部分)

第三章 以文件之名

生成任意大小的文件

$ dd if=/dev/zero of=junk.data bs=1M count=1

记录了1+0 的读入

记录了1+0 的写出

1048576字节(1.0 MB)已复制,0.735955 秒,1.4 MB/秒

查找并删除重复文件

条件:删除那些虽然名字不同但内容一模一样的文件

通过文件内容来识别他们,校验和是依据文件内容来计算的,内容相同的文件自然就生成想通的校验和

通过比较校验和来删除重复文件

书本代码有误,补充如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

<code>#!/bin/bash</code>

<code>ls</code> <code>-lS | </code><code>awk</code> <code>'BEGIN{</code>

<code>getline;getline;</code>

<code>name1=$9;</code>

<code>size=$5</code>

<code>}</code>

<code>{</code>

<code>name2=$9;</code>

<code>if</code> <code>(size==$5)</code>

<code>"md5sum $name1"</code>  <code>| getline;csum1=$1;</code>

<code>"md5sum $name2"</code>  <code>| getline;csum2=$1;</code>

<code>if</code> <code>(csum1==csum2)</code>

<code>print name1;</code>

<code>print name2;</code>

<code>};</code>

<code>size=$5;</code>

<code>name1=name2;</code>

<code>}' | </code><code>sort</code> <code>-u &gt; duplicate_files</code>

<code>cat</code> <code>duplicate_files | </code><code>xargs</code> <code>-I {} md5sum {} | </code><code>sort</code> <code>| </code><code>uniq</code> <code>-w 32 | </code><code>awk</code> <code>'{ print $2 }'</code> <code>| </code><code>sort</code> <code>-u &gt; duplicate_sample</code>

<code>echo</code> <code>Removing..</code>

<code>comm</code> <code>duplicate_files duplicate_sample -2 -3 | </code><code>tee</code> <code>/dev/stderr</code> <code>| </code><code>xargs</code> <code>rm</code> <code>-f</code>

<code>echo</code> <code>Removed duplicates files successfully.</code>

<code>rm</code> <code>duplicate_sample duplicate_files</code>

以不同的用户运行可执行文件

原理:有一个叫做setuid的特殊文件权限,它允许其他用户以文件所有者的身份来执行文件

chown root.root execu_file

chown +s execu_file

./execu_file

这个文件事实上每次以超级用户来运行

setuid的使用不是无限制的,它只能应用在linux ELFG格式二进制文件上,二不能用于脚本

创建文件不可修改

限制:一旦文件呗设置为不可修改,任意用户包括超级用户都不能删除文件,除非其不可修改的属性被移除

通过查看/etc/mtab文件,很容易找出所有挂载分区的文件系统类型

cat /etc/mtab

/dev/sda1 / ext4 rw,errors=remount-ro 0 0

proc /proc proc rw,noexec,nosuid,nodev 0 0

sysfs /sys sysfs rw,noexec,nosuid,nodev 0 0

none /sys/fs/cgroup tmpfs rw 0 0

none /sys/fs/fuse/connections fusectl rw 0 0

none /sys/kernel/debug debugfs rw 0 0

none /sys/kernel/security securityfs rw 0 0

udev /dev devtmpfs rw,mode=0755 0 0

devpts /dev/pts devpts rw,noexec,nosuid,gid=5,mode=0620 0 0

tmpfs /run tmpfs rw,noexec,nosuid,size=10%,mode=0755 0 0

none /run/lock tmpfs rw,noexec,nosuid,nodev,size=5242880 0 0

none /run/shm tmpfs rw,nosuid,nodev 0 0

none /run/user tmpfs rw,noexec,nosuid,nodev,size=104857600,mode=0755 0 0

binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,noexec,nosuid,nodev 0 0

gvfsd-fuse /run/user/zhangjianlin/gvfs fuse.gvfsd-fuse rw,nosuid,nodev,user=zhangjianlin 0 0

可以用chattr将文件设置为不可修改

实战演练

将一个文件设置为不可修改

chattr +i file

或者sudo chattr +i file

rm file出错

移除不可修改的属性

chattr -i file

修改文件三个时间

touch -a 更文件访问时间

touch -m 更改文件内容修改时间

touch -d 时间戳

列举文件夹下的类型统计信息

file -b filename

ASXII text

脚本如下

<code>if</code> <code>[ $</code><code># -ne 1 ];</code>

<code>then</code>

<code>    </code><code>echo</code> <code>$0 basepath;</code>

<code>    </code><code>echo</code>

<code>fi</code>

<code>path=$1</code>

<code>declare</code> <code>-A statarray</code>

<code>while</code> <code>read</code> <code>line;</code>

<code>do</code>

<code>    </code><code>ftype=`</code><code>file</code> <code>-b </code><code>"$line"</code><code>`</code>

<code>    </code><code>let</code> <code>statarray[</code><code>"$ftype"</code><code>]++;</code>

<code>    </code><code>done</code><code>&lt; &lt;(</code><code>find</code> <code>$path -</code><code>type</code> <code>f -print)</code>

<code>                                                                                                                                                                                             </code> 

<code>echo</code> <code>========</code><code>file</code> <code>types and counts==========</code>

<code>for</code> <code>ftype </code><code>in</code> <code>"${!statarray[@]}"</code><code>;</code>

<code>    </code><code>echo</code> <code>$ftype : ${statarray[</code><code>"$ftype"</code><code>]}</code>

<code>done</code>

结果

$ bash filestat.sh .

========file types and counts==========

Bourne-Again shell script, ASCII text executable : 2

empty : 2

原理

while read line

do

  echo $line

done&lt;A  

&lt;A写在最后相当于给整个while do 语句加了一个约束条件,读取文件A里每行至文件尾结束

while read line&lt;A

   echo $line

done

&lt;A写在前面,整个while do语句就没有约束条件, 因为 read line&lt;A这个始终为真

表示 不停地  读取A中的第一行,赋值给参数line,然后打印参数line的值.

done&lt; &lt;(find $path -type f -print) 

&lt;(find $path -type f -print)  等同与文件名。只不过他用子进程输出代替文件名

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

第四章。让文本飞

正则表达式入门

更多内容百度

匹配一个ip地址

[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

grep搜索文本

扩展内容

递归搜索包含词的文件

grep "text" . -R -n #开发人员常用的命令

$ grep "bin" . -R -n 

./第三章:42:binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,noexec,nosuid,nodev 0 0

./第三章:66:#!/bin/bash

./second/mvsuffix.sh:1:#!/bin/bash

./second/mvfilename.sh:1:#a!/bin/bash

./touchlearnfiles.sh:1:#!/bin/bash

./第一章.txt:25:#!/bin/bash

./第一章.txt:36:#!/bin/bash

./第一章.txt:45:#!/bin/bash

./第一章.txt:71:#!/bin/bash

./第一章.txt:74:(cd /bin; ls);

./第一章.txt:97:#!/bin/bash

./第一章.txt:117:#!/bash/bin

./第一章.txt:133:line="root:x:0:0:root:root:/bin/bash"

./第一章.txt:178:#!/bin/bash

./first/password.sh:1:#!/bin/bash

./first/dealpasswd.sh:1:#!/bash/bin

./first/dealpasswd.sh:17:line="root:x:0:0:root:root:/bin/bash"

./first/IFSofdiv.sh:1:#!/bin/bash

./first/array_var.sh:1:#!/bin/bash

./first/cilldshell.sh:1:#!/bin/bash

./first/cilldshell.sh:4:(cd /bin; ls);

./first/delaysleep.sh:1:#!/bin/bash

./first/filetest.sh:1:#!/bin/bash

./第二章.txt:160:#a!/bin/bash

./第二章.txt:196:#!/bin/bash

./third/filestat.sh:1:#!/bin/bash

./third/remove_duplicates.sh:1:#!/bin/bash

在grep 搜索中包括或排除文件

只在目录中递归搜索所有的.c .cpp文件:

$ grep  "main()" . -r --include *.{c,cpp}

搜索中排除所有的README文件

$ grep  "main()" . -r --exclude "README"

对文件中的行、单词和字符进行迭代

实战

迭代文件中的每一行

while read line;

echo $line;

done &lt; file.txt

每一行的单词

for word in $line

echo $word ;

迭代一个单词中方的每一个字符

for ((i=0;i&lt;${#word};i++))

echo

${word:i:1};

${word:start_position:no_of_characters} 返回变量word所包含的字符串中的一个字窜 :重要

cat touchlearnfiles.sh | (while read line; do echo $line; done)

结果:

#!/bin/bash

arrays=("一" "二" "三" "四" "五" "六" "七" "八" "九" "十")

arraynums=(first second third fourth fifth sixth seventh eighth ninth tenth)

read -p "please input the number of caption:" num;

touch "第${arrays[$num-1]}章.txt"

mkdir ${arraynums[$num-1]}

awk打印多列数据,并在列间插入指定的字符

$ ls -l | awk '{ print $1" : " $8 }' 

实战演练:打印不同行或样式之间的文本

打印从第M行到N行这个范围内的所有文本,使用下面语法:

$ awk 'NR==M, NR==N' filename

把M跟N换成数字

$ seq 100 | awk 'NR==4, NR==6'

要打印处于'/start_pattern/,/end_pattern/' filename 

$ cat section.txt

line with pattern1

line with pattern2

line with pattern3

line end with pattern4

line with pattern5

$awk '/pa.*3/, /end/' section

回文判断 最简单的使用命令rev命令

rev 接受一个文件或stdin作为输入,并逆序打印每一行内容

试试下面的代码

<code>#/bin/bah</code>

<code>string=</code><code>"malayalam"</code>

<code>if</code> <code>[[ </code><code>"$string"</code> <code>== </code><code>"$(echo $string | rev )"</code> <code>]]; </code><code>#重点</code>

<code>echo</code> <code>"Palindrome"</code>

<code>else</code>

<code>echo</code> <code>"not palindrome"</code>

解析文本中的点子邮件地址和url

解析email

egrep -o '[A-Za-z0-9.]+@[A-Za-z0-9.]+\.[a-zA-Z]{2,4}'

匹配HTTP URL的正则表达式

egrep -o "http://[a-zA-Z0-9.]+\.[a-zA-A]{2,3}"

http://www.google.com

http://code.google.com

[a-zA-Z0-9.]+ “+”表示应该出现多次

用awk实现head、tail和tac

$ awk 'NR &lt;=10' filename

模拟tail命令打印文件的后10行

$ awk '{ buffer[NR % 10] = $0;} END { for(i=1;i&lt;11;i++){print buffur[i%10] } }' filename

文件切片与参数操作

替换变量内容中的部分文本

$ var="this is a line of text"

$ echo ${var/line/REPLACED}

"This is a REPLACED of text"

$name ${name%$1}$2  #${name%\.*} "%"号除去后缀名,只取文件名

${file_name#*.} 只留扩展名或后缀

生成子窜

${variable_name:start_positon:length}

最后一个字符索引记为-1,使用负数索引的话,必须将负数放入括号内,例如(-1)就是最后一个字符的索引

如 

string={a..z}

echo ${string:(-2):2}

yz

本文转自lilin9105 51CTO博客,原文链接:http://blog.51cto.com/7071976/1251296,如需转载请自行联系原作者

继续阅读