linux学习:文件处理相关命令用法整理(正则表达式)
指令:ls、cat、du、stat、rename、dirname、basename、sort、diff、seq、head、tail、tree、chmod、cut、paster、正则
一:统计文件大小,行数,字符数相关命令
统计文件行数、单词数和字符数
wc file #统计文件行数,单词数,字符数
wc -l file #统计文件行数
cat file | wc -l #将stdin作为输入
wc -w file #统计文件单词数
cat file | wc -w
wc -c file #统计文件字符数
cat file | wc -c
wc file -L #打印最长行的长度
ls -l | grep "^-" | wc -l #统计当前文件夹下的文件个数
ls -lR | grep "^-" | wc -l #递归统计当前文件夹下的文件个数(包含子目录里的)
ls -l | grep "^d" | wc -l #统计当前文件夹下目录的个数
ls -lR | grep "^d" | wc -l #递归统计当前文件夹下目录的个数(包含子目录里的)
迭代文件中的行,单词,字符
1、用子shell迭代行
cat test.txt | ( while read line; do echo $line; done )
2、迭代行再迭代每一行中的每个单词
while read line;
do
for word in $line
do
if [[ $word == 'test' ]]; then
echo $word;
fi
done
done < test.txt
3、迭代一个单词中的每一个字符,$(#word)返回变量word的长度,使用特殊标记法 ${string:i:num} string为要迭代的字符串;i为每次迭代的第i个字符;num为从i开始往后取num个字符。
for((i=0;i<${#word};i++))
do
echo ${word:i:1} ;
done
4、迭代文件每一行,匹配到相应条件并打印,将 from 后面的字符串打印出来
IFS_OLD=$IFS
IFS=$'\n'
for i in `cat /tmp/sql_recodes.log `;do echo ${i#*'from'}; done | less
IFS=$IFS_OLD
文件大小,操作
du file.txt #查看file.txt占用的磁盘空间,默认以字节作为单位
du file1 file2 file3 ... #查看多个文件的大小
du -a /data/test #查看/data/test目录下所有文件的大小
du -h file.txt #以KB,MB,GB显示文件占用的磁盘数更容易阅读
du -h /data/test #以KB,MB,GB递归显示目录占用的磁盘数更容易阅读
du -s file.txt #参数-s表示只输出合计数据
du -c file1 file2 ... #输出所有文件占用的磁盘数量,并在最后显示总数
du -b file #打印以字节为单位的文件大小
du -k file #打印以KB为单位的文件大小
du -m file #打印以MB为单位的文件大小
du -B BLOCK_SIZE file #打印以指定块为单位的文件大小,如:du -B 4 test.sh
du --exclude "*.txt" /data/test #打印/data/test目录中处理.txt文件外的所有文件的大小
du --exclude-from list.txt /data/test #打印/data/test目录总不在list.txt中列出的文件中的文件的大小
du -ak /data/test | sort -nrk 1 | head -n 5 #打印/data/test目录中最大的5个文件和目录
find . -type f -exec du -k {} \; | sort -nrk 1 | head #打印当前目录中最大的10个文件
du -h --max-depth=1 #打印当前文件夹下所有文件和目录大小,--max-depth=n表示只深入到第n层目录
du -h --max-depth=1 | grep M #找出大小超过1M的文件和目录
#判断文件是否存在
if [[ -s $file ]]; then
echo "not empty"
fi
#stat 查看文件详细信息(包括权限,归属,大小,访问时间和修改时间等)
stat [-ftLc] filename
-f 查看文件所在文件系统状态信息
-t 以简洁形式输出文件信息
-L 显示软连接原始文件状态信息
-c 按照指定格式输出
用例:
stat -c %U test.sh #获取文件属于哪个用户
stat -c %u test.sh #获取文件所属用户的用户ID
stat -c %G test.sh #获取文件属于哪个用户组
stat -c %g test.sh #获取文件属于哪个用户组的组ID
stat -c %m test.sh #获取文件的磁盘挂载点
stat -c %x test.sh #获取文件的访问时间
stat -c %y test.sh #获取文件的修改时间
stat -c %z test.sh #获取文件的更改时间
stat -c %A test.sh #获取文件权限,如 -rw-r--r--
stat -c %a test.sh #获取文件权限,如 644
stat -c %s test.sh #获取文件大小(字节数)
wc -c $file #判断文件大小
mdate="${str:7:10}" #从字符串中截取日期,比如变量str="testlog2020-01-01.txt"
newstr=${oldstr//aaa/bbb} #比如变量 old_str="this is aaa test text", newstr="this is bbb test text"
rename '*.bak' '' *.bak #去掉所有bak后缀
dirname ‘/home/lalor/a.txt' #获取路径名 :/home/lalor
basename ‘/home/lalor/a.txt' #获取文件名 :a.txt
#把所有空格改成下划线
find path -type f -exec rename 's/ /_/g' {} \;
#删除前3行
$cat a.txt | sed 1,3d
二:文件排序,对比,打印与权限相关命令
排序和去重:sort 与 uniq
sort test.txt test2.txt > sorted.txt #对一个或多个文件以行为单位按照ASCII码的顺序进行排序,再把排序结果从定向到sorted.txt
sort test.txt test2.txt -o sorted.txt #同上
cat sorted.txt | uniq > sort_uniq.txt #对已排序的文件找出不重复的行并重定向到sort_uniq.txt文件
sort test.txt | uniq #排序并去重(重复的行中会保留一行)
sort -u test.txt #同上
sort -n test.txt #参数-n指定按数字进行排序
sort -r test.txt #参数-r指定按逆序进行排序
sort -M test.txt #参数-M指定按月份进行排序
sort -m sorted1.txt sorted2.txt #合并两个排过序的文件,并且不需要对合并后的文件再进行排序
sort -k 2 test.txt #参数 -k 指定根据第二个键(列)进行排序
sort -nk 2,3 test.txt #?
sort -nrk 1 test.txt #将test.txt文件按照第一列的的数字进行逆向排序
sort -z test.txt | xargs -0 #终止符\0使得xargs命令的使用更加安全
sort -bd test.txt #参数-b用户忽略文件中的前导空白字符,参数-d用户指明以字典序进行排序
uniq -u test.txt #只显示唯一的行,(重复的行全部去掉,一行也不保留)
sort test.txt | uniq -u #同上
sort test.txt | uniq -c #排序后统计各行在test.txt文件中出现的次数
sort test.txt | uniq -d #排序后找出test.txt文件中重复的行
sort test.txt | uniq -s 2 -w 3 #使用醒目的字符作为对比的列,通过参数 -s 2 忽略了前2个字符,使用参数 -w 3 指定用于比较的最大字符数为3
echo "ahebhaaa" | sed 's/[^\n]/&\n/g' | sed '/^$/d' | sort | uniq -c | tr -d '\n' #管道 sed 's/[^\n]/&\n/g' 为每个字符后面追加一个换行符;管道 sed '/^$/d' 删除最后多出的那个换行符;管道 sort 对每一行进行排序(前面这样做是要拆分成行,因为sort只能进行行排序);管道uniq -c 打印每一行的重复次数; 管道 tr -d '\n' 将输入中的空格和换行符删除。结果:4a1b1e2h
----------------------------------------
#!/bin/bash
#测试一个文件是否已经排序
sort -C file ;
if [ $? -eq 0 ]; then
echo Sorted;
else
echo Unsorted;
fi
#要检查是否按数字进行排序 则使用sort -nC
-----------------------------------------
打印文件行:cat
echo 'Text through stdin' | cat - file.txt #将输入文件的内容与标准输入拼接在一起
cat -s filename #压缩filename文件中连续的多个空白行成单个
cat filename | tr -s '\n' #输出移除空白行后的filename内容,tr将连续的多个'\n'字符压缩成单个'\n'
逆序打印行:tac
tac file #逆序打印文件
seq 5 | tac #输出:54321
file test.txt #确定文件的类型、
文件类型统计信息
---------------------------------------
#!/bin/bash
#filename:test.sh
#执行:./test.sh /data/test
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
------------------------------------------
对比文件差异与修补
diff test1.txt test2.txt #test2.txt相对于test1.txt文件多了哪些行少了哪些行。
diff -u test1.txt test2.txt #参数-u用于生成一体化输出,可读性更好一点。以+号起始的表示新加入的行,以-号起始的表示删除的行。
diff -u test1.txt test2.txt > test.patch #(1)将输出重定向到test.patch文件
patch -p1 test1.txt < test.patch #(2)将修改应用于test1.txt文件,此时test1.txt和test2.txt文件的内容一模一样。
patch -p1 test1.txt < test.patch #撤销修改,也可加个-R参数跳过询问
打印文件
head file #打印文件前10行
cat file | head #同上
head -n 5 file #打印文件前5行
head -n -6 file #打印除了最后6行之外的所有行
seq 11 | head -n -5 #打印除了最后数字7到11这5行之外的所有行,即数字1到6
seq 100 | head -n 5 #打印数字1到5这5行。而不打印数字6到100这95行
tail file #打印文件最后10行
cat file | tail #同上
tail -f file #打印文件最后10行,并随着数据的增加时时保持更新,动态打印
tail -n 5 file #打印最后5行
tail -n +(10+1) #打印除了了前10行之外的所有行
seq 100 | tail -n +6 #打印除了前5行之外的所有行即第6到第100行。6=N+1,所以N=5
head -n 200 filename | tail -n 100 #打印文件第100到第200行。同理可做分页查看文件内容
tail -n 1000 filename | heal -n 200 #打印文件倒数第1000行到倒数第800行
列出文件
ls -d */ #只列出当前目录下的所有目录
ls -F | grep "/$" #同上
ls -l | grep "^d" #列出当前目录下所有目录的详细信息
打印目录
tree path #打印path的目录树
tree path -P "*.php" #打印path目录树,只显示目录树中的php文件
tree path -I "*.php" #打印path目录树,只显示目录树中的除PHP文件外的文件
tree -h path #打印出文件和目录大小
tree path -H http://localhost -o out.html #生成一个包含目录树输出的HTML文件
文件与目录权限:
chmod u=rwx g=rw o=x filename #设文件权限,用户权限为rwx,用户组权限为rw,其他实体权限为x(u指user,即文件的拥有者;g指group,即文件拥有者所属的用户组;o指other,其他)
chmod o+w filename #给其他用户增加文件的写权限
chmod g-r filename #删除用户组对文件的读权限
chmod a+x filename #给所有用户增加文件的执行权限(a指all,表示所有用户)
chmod a-w filename #删除所有用户对文件的写权限
chmod 755 filename #设置文件的权限为755(r--=4, -w-=2, --x=1;rw-=6,rwx=7,-wx=3,r-x=5),755分别对应user,group,other用户的权限。
chmod a+t dir_name #设置粘滞位应用于dir_name目录。(粘滞位是一种应用于目录的权限类型,使得只有目录的所有者才能删除目录中的文件,即使是用户组和其他用户有足够的权限也不能执行删除操作)
chmod 755 . -R #递归设置当前目录及子目录的权限为755
chmod 755 "($pwd)" -R #同上
chown user:group filename #设置文件属于用户user,属于用户组group
chown user.group filename #同上
chown root:root filename #设置文件属于root用户,属于root用户组
chmod user:group filename -R #以递归方式设置所有权
sudo adduser username #增加用户
sudo deluser username #删除用户
passwd #修改当前用户的密码
sudo passwd username #修改用户密码:
sudo chfn userid #修改用户资料
sudo usermod -L username #禁用某个帐户
sudo passwd -l username #禁用某个帐户
sudo usermod -U username #启用某个帐户
sudo passwd -u username #启用某个帐户
sudo usermod -G admin -a username #增加用户到admin组
对系统文件进行保护,就算使用root用户也无法修改和删除:
chattr [-RV][-v<版本编号>][+/-/=<属性>][文件或目录...]
这项指令可改变存放在ext2文件系统上的文件或目录属性,这些属性共有以下8种模式:
a:让文件或目录仅供附加用途。
b:不更新文件或目录的最后存取时间。
c:将文件或目录压缩后存放。
d:将文件或目录排除在倾倒操作之外。
i:不得任意更动文件或目录。
s:保密性删除文件或目录。
S:即时更新文件或目录。
u:预防意外删除。
参数:
lsattr [-adlRvV][文件或目录...]
参数:
-d 显示,目录名称,而非其内容。
-l 此参数目前没有任何作用。
-R 递归处理,将指定目录下的所有文件及子目录一并处理。
-v 显示文件或目录版本。
-V 显示版本信息。
例子:
chattr +i /etc/test.conf #设置文件为不可修改,防止文件被修改(root也无法更改)
lsattr /etc/resolv.conf #查看chattr修改后的属性:----i-------- /etc/test.conf
chattr -i /etc/test.conf #解除该不可修改设置,回归常规的文件权限
chattr +a /var/log/test.log #让某个文件只能往里面追加数据,但不能删除,适用于各种日志文件
三:文件切分,合并与重命名相关命令
分割文件:split && csplit
split -b 10k test.txt #将test.txt文件分割为多个文件,每个文件大小为10k,分别以xaa、xab、xac...命名
split -b 10k test.txt -d -a 3 #将test.txt文件分割为多个文件,每个文件大小为10k。参数-d表示以数字为后缀,-a 3 表示后缀长度为3,比如x009,x019,x029,x039...
split -l 100 test.txt #参数-l 100 是指分割成多个文件每个文件包含100行
split -b 10k test.txt -d -a 3 xst #功能与前面相同,但是分割后的文件命名以xst为前缀:xst009、xst019、xst029、xst039...
除了k(KB),其他单位还有M(MB),G(GB),c(byte),w(word)等。
------------------------------------------------------
假设有个文件test.txt:
SERVER-1
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbb
ccccccccccccccccc
SERVER-2
ddddddddddddddddd
eeeeeeeeeeeeeeeee
fffffffffffffffff
SERVER-3
gggggggggggggggggg
hhhhhhhhhhhhhhhhhh
iiiiiiiiiiiiiiiiii
csplit test.txt /SERVER/ -n 2 -s {*} -f server -b "%02d.log"
rm server00.log
#/SERVER/ 表示要匹配的文本样式,包括从当前行(包含)到下一行包含“SERVER”的行(不包含)。
#{*}表示匹配重复分割知道文件结尾。可用{整数}的形式来指定执行分割的次数
# -s 使命令进入静默模式,不打印其他信息
# -n 指定分割后的文件名后缀的数字个数,例如01,02,03等。
# -f 指定分割后的文件名前缀,-f server 指定前缀为server
# -b 指定后缀格式。-b "%02d.log"
因为分割后的第一个文件没有任何内容,故删除。
----------------------------------------------------
文件名切分
------------------------------------
#!/bin/bash
file="test.png" #对于文件名类似file="test.txt.png.log" 这种类型可使用贪婪模式 %% 或者 ##
name=$(file%.*) #文件名切分 %操作符表示非贪婪的删除位于%右侧的通配符所匹配的字符串 贪婪模式:name=${file%%.*}
ext=$(file#*.) #文件扩展名 #操作符表示非贪婪的删除位于#左侧的通配符所匹配的字符串 贪婪模式:ext=$(file##*.)
echo $name,$ext #输出结果:test,png
------------------------------------
按列切分文件
cut命令:
cut [-bn] [file] 或 cut [-c] [file] 或 cut [-df] [file]
使用说明
cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。
如果不指定 File 参数,cut 命令将读取标准输入。必须指定 -b、-c 或 -f 标志之一。
主要参数
-b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。
-c :以字符为单位进行分割。
-d :自定义分隔符,默认为制表符。
-f :与-d一起使用,指定显示哪个区域。
-n :取消分割多字节字符。仅和 -b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的<br />范围之内,该字符将被写出;否则,该字符将被排除。
cut -f 2,3 filename #显示文件第2列和第3列
cut -f 2,3,7 filename #显示文件第2列和第3列和第7列
grep "Invalid user" /var/log/auth.log | cut -d ' ' -f 10 #获取/var/log/auth.log 中包含“Invalid user”的行,并按照空格拆分行(-d ' ' 参数)获取第10个字符串(-f 10 参数)
按列合并文件
paste file1 file2 file3 ...
paste test1.txt test2.txt #将test1.txt的每一列与test2.txt的每一列依次拼接起来。
paste test1.txt test2.txt -d "," #参数-d明确指定定界符为逗号
批量重命名文件和移动
rename *.JPG *.jpg #建*.JPG 更名为*.jpg
rename 's/ /_/ge' * #将文件名中的空格替换成字符"_";test_12.jpg
rename 'y/A-Z/a-z/' * #转换文件名为小写
rename 'y/a-z/A-Z/' * #转换文件名为大写
rename -v 's/img_(\d{2})\.jpeg/test_$1.jpg/' ./*.jpeg #将当前目录下所有img_*.jpeg文件重命名为 test_*.jpg 文件,比如 img_12.jpeg 重命名为 test_12.jpg,子模式‘\d{2}’会捕捉2个连续的数字,对应$1。
rename -v 's/test_(\d{1})_(\d{8}).log/$2_$1_test.log/' ./test*.log #将当前目录下所有 test_2_20180101.log 格式的文件 重命名为 20180101_2_test.log 格式,子模式‘\d{8}’会捕捉8个连续的数字,对应$2。
find . -type f -exec rename 's/ /_/ge' {} \; #将所有文件名中的空格替换为字符"_";
for i in `ls`; do mv -f $i `echo $i | tr a-z A-Z`; done #所有小写字母转换成大写字母
for i in `ls`;do mv $i abc_$i;done #当前目录下所有文件都加上“abc_”前缀
for i in `ls`;do mv $i $(sed -r 's/abc_(.*)/\1/' <<< $i);done #当前目录下所有文件都去掉“abc_"前缀
for i in `ls`; do mv -f $i `echo $i | sed 's/^.../test_/'`; done #替换文件名前面3个字符为test_,一个点表示一个字符,也可以把前面10个字符换成test_
for i in `ls`; do mv -f $i `echo $i | sed 's/^/test_/'`; done #在所有文件名前面加上 test_ 前缀
for i in `ls`; do mv -f $i `echo "test_"$i`; done #同上,在所有文件名前面加上 test_ 前缀
for i in `ls`; do mv -f $i `echo $i | sed 's/...$/_test/'`; done #替换文件名后面面3个字符为 _test,一个点表示一个字符,也可以把前面10个字符换成 _test
for i in `ls`; do mv -f $i `echo $i | sed 's/$/_test/'`; done #在所有文件名前面加上 _test 后缀
for i in `ls`; do mv -f $i `echo $i"_test"`; done #同上,在所有文件名前面加上 ——test 后缀(会直接夹在扩展名后面)
for i in `ls`; do mv -f $i `echo $i | awk -F [_.] '{print $3"_"$2"_"$1"."$4}'`; done #批量从命名文件,将格式 test_11001_201903011212.log 重命名为 201903011212_11001_test.log 格式
-------------------------------------
#!/bin/bash
#批量重命名图片文件
count=1;
for img in *.jpg *.png #依次取所有的jpg和png文件(.jpg可以改成 .[Jj][Pp][Gg] 从而匹配不区分大小写)
do
new=image-$count.${img##*.}
mv "$img" "$new" 2> /dev/null # 2> 将mv命令的标准错误(stderr)重定向到/dev/null.防止错误信息打印到终端
if [$? -eq 0]; # $?用于检查退出状态,即最近执行的命令没有错误,$?的值为0.否则$?为非0
then
echo "Renaming $img to $new"
let count++
fi
done
--------------------------------------
四、shell正则表达式
匹配中文字符的正则表达式:[u4e00-u9fa5]
匹配双字节字符(包括汉字在内):[^x00-xff]
匹配空白行的正则表达式:^ *$
匹配HTML标记的正则表达式:<(S*?)[^>]*>.*?</1>|<.*? />
匹配首尾空白字符的正则表达式:^s*|s*$
匹配Email地址的正则表达式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
匹配网址URL的正则表达式:[a-zA-z]+://[^s]*
匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
匹配国内电话号码:d{3}-d{8}|d{4}-d{7}
匹配腾讯QQ号:[1-9][0-9]{4,}
匹配中国邮政编码:[1-9]d{5}(?!d)
匹配身份证:d{15}|d{18}
匹配ip地址:d+.d+.d+.d+
匹配特定数字:
^[1-9]d*$ #匹配正整数
^-[1-9]d*$ #匹配负整数
^-?[1-9]d*$ #匹配整数
^[1-9]d*|0$ #匹配非负整数(正整数+ 0)
^-[1-9]d*|0$ #匹配非正整数(负整数+ 0)
^[1-9]d*.d*|0.d*[1-9]d*$ #匹配正浮点数
^-([1-9]d*.d*|0.d*[1-9]d*)$ #匹配负浮点数
^-?([1-9]d*.d*|0.d*[1-9]d*|0?.0+|0)$ #匹配浮点数
^[1-9]d*.d*|0.d*[1-9]d*|0?.0+|0$ #匹配非负浮点数(正浮点数+ 0)
^(-([1-9]d*.d*|0.d*[1-9]d*))|0?.0+|0$ #匹配非正浮点数(负浮点数+ 0)
匹配特定字符串:
^[A-Za-z]+$ #匹配由26个英文字母组成的字符串
^[A-Z]+$ #匹配由26个英文字母的大写组成的字符串
^[a-z]+$ #匹配由26个英文字母的小写组成的字符串
^[A-Za-z0-9]+$ #匹配由数字和26个英文字母组成的字符串
^w+$ #匹配由数字、26个英文字母或者下划线组成的字符串