shell--文件操作1


1.遍历目录,查找其中所有文件,并统计每个文件的行数

定义一个函数detect,这是为了可以递归往子目录中操作

接着一个循环遍历`ls $1`的结果,$1是第一个输入参数,也即查找路径

在循环中,首先判断文件是否是目录文件,如果是,则递归进入里边,

否则用wc命令得到文件中行的数目,并用cut命令得到wc结果中的行数,最后把结果保存到/home/user/shell/reslt.txt里边就好啦。

最后调用下这个函数。

#!/bin/sh
function detect(){
for file in `ls $1`
do
if [ -d $1"/"$file ]
then
  detect $1"/"$file
else
  wc -L $1"/"$file | cut -d' ' -f 1-2>> /home/user/shell/result.txt
fi

done
}
path="/home/user/"
detect $path


wc命令

wc即wordcount,可以统计文件的相关信息。

  • -l选项统计行数
  • -c统计字节数
  • -w统计字数,字由空格,换行等区分
  • -L,最长行的长度(字符个数,比如aaa长度为3)

因为它的输出是“num  文件名”的形式,比如
root@ubuntu:/home/user/shell# wc -l t.sh
15 t.sh

所以要得到15的话就要使用cut命令了

ls -l | wc -l 可以用来统计当前路径下文件总数

cut命令

  • -b以字节为单位分割,注意的是wc里边是没有-b选项的哦
  • -c以字符为单位分割,感觉和-b差不多啊,每一个字符都是用一个字节来存储的,像'\t'这样的也是嘛
  • -d自定义分隔符,可以用空格,或者字符之类的
  • -f与-d合作,指定显示分割区域的哪一部分,分割部分的序号从1开始
a x dd
bb x zz
ccc x dd
root@ubuntu:/home/user/shell# cut -d'x' -f2 ls
 dd
 zz
 dd
root@ubuntu:/home/user/shell# cut -d'x' -f1,2 ls
a x dd
bb x zz
ccc x dd
root@ubuntu:/home/user/shell# cut -d' ' -f1-3 ls
a x dd
bb x zz
ccc x dd

-d后边紧跟' ',单引号里边填充自定义分隔符,上面实验了字符x和空格, -f后则跟数字,表示输出的区域

从里面可以发现,如果输出的区域是连续的两个区域,那么分割它们的分隔符在输出的时候也是会输出的哦!

如果想要让一个变量作为分割的输入,该怎么写呢?用echo命令

var="abc x ec x dd"
echo $var | cut -d'x' -f1,2
输出为abc x ec 


如果想把文件作为输入的话,在最后边加文件路径就可以啦!
root@ubuntu:/home/user/shell# cut -c 1-5 /home/user/shell/ls
a x d
bb x 
ccc x



2.读入文件遍历每一行

如下读入文件并遍历每一行,取每行的第一个数字,之后累加
#!/bin/sh
path="/home/user/shell/result.txt"
sum=0 
while read myline 
do
  num=`echo $myline |cut -d' ' -f1`
  echo $num  
  sum=`expr $num + $sum`   
done < $path
echo "sum is "$sum 
             
这是一种方式,即

while read line

do

done < file

如下方式都可以

cat file | while read line

do 

done

很奇怪的是,上面这种方式运行上面这个脚本,最后输出的sum依然是0,不知道肿么回事,好奇怪哦!难道循环里边的突然都变成局部变量了?然后修改就没用啦?


3.把一个文件夹中的文件后缀名改为bat


改名用mv操作,mv操作可以用来改名或是移动文件

#!/bin/sh
path="/home/user/data"
for file in `ls $path`
do
  new_file=${file%.*}".bat"
  if [ ! -e $path"/"$new_file ]
  then
  mv $path"/"$file $path"/"$new_file
  fi
  tmp=$(date +%Y%m%d:%H%M%S)
  tmp2=`date +%Y`
 echo $tmp $tmp2 
done


mv命令

mv [选项] 源文件或目录 目标文件或目录
视mv命令中第二个参数类型的不同(是目标文件还是目标目录),mv命令将文件重命名或将其移至一个新的目录中。当第二个参数类型是文件时,mv命令完成文件重命名,此时,源文件只能有一个(也可以是源目录名),它将所给的源文件或目录重命名为给定的目标文件名。当第二个参数是已存在的目录名称时,源文件或目录参数可以有多个,mv命令将各参数指定的源文件均移至目标目录中。在跨文件系统移动文件时,mv先拷贝,再将原有文件删除,而链至该文件的链接也将丢失。

移动多个文件到一个目录的话:
mv srcfile1 srcfile2 ...  dstdir
或者
mv -t dstdir srcfile1 srcfile2 ...
如下
root@ubuntu:/home/user/shell# ls
d.sh  ls  result.txt  t2.sh  test2.sh  t.sh
root@ubuntu:/home/user/shell# mkdir dir
root@ubuntu:/home/user/shell# mv t.sh t2.sh dir
root@ubuntu:/home/user/shell# ls
dir  d.sh  ls  result.txt  test2.sh
root@ubuntu:/home/user/shell# ls dir
t2.sh  t.sh
root@ubuntu:/home/user/shell# cd dir
root@ubuntu:/home/user/shell/dir# ls ../
dir  d.sh  ls  result.txt  test2.sh
root@ubuntu:/home/user/shell/dir# mv -t ../ t.sh t2.sh
root@ubuntu:/home/user/shell/dir# ls
root@ubuntu:/home/user/shell/dir# ls ../
dir  d.sh  ls  result.txt  t2.sh  test2.sh  t.sh
root@ubuntu:/home/user/shell/dir# 

截断命令

${file#*/}:       拿掉第一条/及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}:    拿掉最后一条/及其左边的字符串:my.file.txt
${file#*.}:       拿掉第一个.及其左边的字符串:file.txt
${file##*.}:    拿掉最后一个.及其左边的字符串:txt
${file%/*}:     拿掉最后条/及其右边的字符串:/dir1/dir2/dir3
${file%%/*}: 拿掉第一条/及其右边的字符串:(空值)
${file%.*}:    拿掉最后一个.及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}: 拿掉第一个.及其右边的字符串:/dir1/dir2/dir3/my
记忆的方法为:
      #是去掉左边, ##最后一个
      %是去掉右边, %%第一个
注意写的顺序,*究竟是放在/左边还是右边是根据*和%来变化的,如果是*,那么截断左边的,所以放在左边,%截断右边的,所以放到右边

date命令

格式里边的+%Y...,+号后边紧跟%哦要不就出错了!上面例子就是年月日:时分秒

4.输入一个文件名,判断在当前目录是否存在

#!/bin/sh
filepath=$(pwd)
echo $filepath
echo "read a file name:"
read name
if [ -e $filepath"/"$name ]
then
  echo "exist"
else
  echo "not exist"
fi
当前目录可以用pwd命令得到,$()可以得到命令的结果,
比如$(expr 1 + 2)
我看到过有一个写成 $(cd "$(dirname $0)" | pwd)的命令来获取当前目录,$0就是当前脚本文件名,但实际上运行的时候,比如我的是t.sh
运行时敲命令./t.sh
那么$0也就是./t.sh,所以$(dirname $0)也就是".",不就是当前目录嘛。那么cd还有什么意义呢?很奇怪啊

好吧,确实是有意义的,比如说我的shell文件放在/home/user/shell里边,
但我在/home/user里边执行这个shell文件

#!/bin/sh
filepath=$(dirname $0)
echo $filepath
cd $(dirname $0)
filepath2=$(pwd)
echo $filepath2
pwd
echo "read a file name:"
read name
if [ -e $filepath2"/"$name ]
then
  echo "exist"
else
  echo "not exist"
fi
root@ubuntu:/home/user# ./shell/t.sh
./shell
/home/user/shell
/home/user/shell
read a file name:
t.sh
exist

$0是./shell/t.sh,所以dirname $0也就是./shell,cd ./shell也就进入了shell目录啦。
注意"."是此时的当前目录,shell则是当前目录的子目录,所以也就是进入当前目录的shell子目录里边。
如果写成cd /shell,那么"/"代表的是根目录的!!
cd ..则是进入当前目录的父目录。
运行中海油一个很奇怪的问题是如果我把cd命令和pwd命令合起来写,结果cd命令就没有执行,很奇怪。





你可能感兴趣的:(shell--文件操作1)