第三章 以文件之名
生成任意大小的文件
$ dd if=/dev/zero of=junk.data bs=1M count=1
记录了1+0 的读入
记录了1+0 的写出
1048576字节(1.0 MB)已复制,0.735955 秒,1.4 MB/秒
查找并删除重复文件
条件:删除那些虽然名字不同但内容一模一样的文件
通过文件内容来识别他们,校验和是依据文件内容来计算的,内容相同的文件自然就生成想通的校验和
通过比较校验和来删除重复文件
书本代码有误,补充如下
#!/bin/bash ls -lS | awk 'BEGIN{ getline;getline; name1=$9; size=$5 } { name2=$9; if (size==$5) { "md5sum $name1" | getline;csum1=$1; "md5sum $name2" | getline;csum2=$1; if (csum1==csum2) { print name1; print name2; } }; size=$5; name1=name2; }' | sort -u > duplicate_files cat duplicate_files | xargs -I {} md5sum {} | sort | uniq -w 32 | awk '{ print $2 }' | sort -u > duplicate_sample echo Removing.. comm duplicate_files duplicate_sample -2 -3 | tee /dev/stderr | xargs rm -f echo Removed duplicates files successfully. rm duplicate_sample duplicate_files
以不同的用户运行可执行文件
原理:有一个叫做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
脚本如下
#!/bin/bash if [ $# -ne 1 ]; then echo $0 basepath; echo fi path=$1 declare -A statarray while read line; do ftype=`file -b "$line"` let statarray["$ftype"]++; done< <(find $path -type f -print) echo ========file types and counts========== for ftype in "${!statarray[@]}"; do echo $ftype : ${statarray["$ftype"]} done
结果
$ bash filestat.sh .
========file types and counts==========
Bourne-Again shell script, ASCII text executable : 2
empty : 2
原理
while read line
do
echo $line
done<A
<A写在最后相当于给整个while do 语句加了一个约束条件,读取文件A里每行至文件尾结束
while read line<A
do
echo $line
done
<A写在前面,整个while do语句就没有约束条件, 因为 read line<A这个始终为真
表示 不停地 读取A中的第一行,赋值给参数line,然后打印参数line的值.
done< <(find $path -type f -print)
<(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 < file.txt
每一行的单词
for word in $line
do
echo $word ;
done
迭代一个单词中方的每一个字符
for ((i=0;i<${#word};i++))
do
echo
${word:i:1};
done
${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
line with pattern3
line end with pattern4
回文判断 最简单的使用命令rev命令
rev 接受一个文件或stdin作为输入,并逆序打印每一行内容
试试下面的代码
#/bin/bah string="malayalam" if [[ "$string" == "$(echo $string | rev )" ]]; #重点 then echo "Palindrome" else echo "not palindrome" fi
解析文本中的点子邮件地址和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 <=10' filename
模拟tail命令打印文件的后10行
$ awk '{ buffer[NR % 10] = $0;} END { for(i=1;i<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