一:基本命令部分
1.查找系统中所有文件长度为0的普通文件,并列出它们的完整路径;
find / -type f -size 0 -exec ls -l {} ;
2.查找/zsh目录中更改时间在7日以前的普通文件,并在删除之前询问它们;
find /zsh -type f -mtime +7 -ok rm {}
3.myfile.html内容如下:
<b>This</b> is what <b>I</b> meant.
删除HTML标记,也就是要得到:
This is what I meant.
cat myfile.html | sed 's/<br>//g;s/</br>//g'
4.使用tr命令将指定文件的空行删除
tr -s [' ']<filename
5.在txt目录下搜索所有包含有‘the’单词的.c文件,列出文件名
grep -lr 'the' *.c
6.使用grep将express文件里以数字开头的行删除掉
grep '^[^0-9]' express
7.让电脑10秒钟后重启
sudo shutdown -r +10 10分钟 sleep 10;sudo shutdown -r now 10秒
8.在shell执行命令时,屏蔽掉错误信息。
2>dev/null
9.解释命令:trap ‘echo hello int’ INT。
当您运行Ctrl+C 等中断时,会自动运行echo命令
10.强制结束指定进程号的进程
kill -9 id (id为进程号)
11.将某个文件的属性更改为只有root可读写执行
chown root filename chmod 700 filename
12.查出系统中所有用户标识号大于99的用户
cat /etc/passwd | awk -F ':' '{if($3>99) print $1}'
13.统计系统中用户标识号大于99的用户数
cut -d: -f 1,3 /etc/passwd | grep '[0-9]{3,}' | wc -
14 .按文件大小的降序列出目录中的所有文件
ls -l | sort -nrk 5
15.将当前目录下的所有文件打包成一个文件
tar czvf filename.tar.gz $(ls)
或
tar czvf filename.tar.gz .
16.解释命令:ln a b
ln 源文件 目标文件:为a生成一个硬连接b,hard link占磁盘空间
17.用命令方式将一个进程暂停
kill -STOP id(id为进程号)
18.解释命令:find -name hello.c -exec ls -l {} ;
查找当前目录中所有hello.c文件列出它们的详细信息
19.解释命令:grep –n ‘^[^a-zA-Z]’ express
输出express文件中不以字母开头的行,并显示行号
20.解释命令:grep –v ‘^$’ express | grep –v ‘^#’
输出express文件中的非空行和非#号开头的句子
21.解释命令:grep –n ‘o{2}’ express
输出含有两个o的句子
22.解释命令:grep –n ‘^(.).*1$’ expres
输出匹配一行中头一个字符跟最后一个字符的行
23.解释命令:cat -n express | sed 'd;n'
读一行,删一行,读一行,显示出来是空的;
24.解释命令:cat -n express | sed -n 'p;N'
输出奇数行
25.解释命令:cat -n express | sed -n 'N;p'
偶数行就全部输出,奇数行就最后一行不输出
26.解释命令:sed = express | sed 'N;s/ /:/'
打印行号并在行号和句子之间添加冒号
27.解释命令:sed '$!N;/^(.*) 1$/!P;D' chongfu
删除重复行后输出
28.解释命令:sed -e '1!G;h;$!d' express
文件倒着输出
29.解释命令:echo "WeLoveChinaUnix"|sed -e 'H;s/(..).*/1/;x;s/.*(.{9})$/1/;x;G;s/ / /'
输出We ChinaUnix
二:分别使用sed和awk实现下面的功能(使用express文件)
30.在每一行后面增加一空行
sed:
sed G express
awk:
awk ‘{print $0 "
"}’ express
31.设置文本中每一行后面有且只有一空行。
sed: sed 's/^$/d;G' express awk:
awk '!/^$/{printf("%s ",$0)}' express
32.在每行后面增加2行空行
sed:
sed '/^$/d;G;G' express
awk:
awk '!/^$/{printf("%s ",$0)}' express
33.删除所有偶数行
sed: sed 'n;d' express awk: awk '{if(NR%2!=0) print $0}' express
34.在匹配The的行前插入空行
sed:
sed '/The/{x;p;x}' a.c
awk:
awk '{if(/The/)printf(" %s ",$0);else print $0}' a.
35.输出行号,行号和正文间加冒号
sed = express | sed 'N;s/ /:/'
awk '{printf("%d:%s ",NR,$0)}' a.c
-
对文件中的所有非空行编号
-
计算行号(模拟 “wc -l”)
sed -n '$=' express
关于WC命令:
wc就是word count(数字数)的缩写,通常利用Linux的wc命令和其他命令结合来计算行和其他信息。在Linux下用wc进行计数。返回文件的行数、字数、字节数等。
wc -m filename:显示一个文件的字符数
wc -l filename:显示一个文件的行数
wc -L filename:显示一个文件中的最长行的长度
wc -w filename:显示一个文件的字数
sed相关的命令参数:
-n, --quiet, --silent
安静模式,取消默认输出。
$:锚定行的结束如:/sed$/匹配所有以sed结尾的行。
=:打印当前行号
相关解释:
$=表示打印最后一行的行号,-n表示安静模式,不会输出其他行的相关内容
awk 'END {print NR}' express
awk相关的知识点:
BEGIN和END
在awk 中两个特别的表达式,BEGIN和END,这两者都可用于pattern中,提供BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。任何在BEGIN之后列出的操作(在{}内)将在awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。
所以awk 'END {print NR}'也就是在读取到最后一行之后,才输出对于的行号,也就是输出该文件的行数。
-
模拟dos2unix
实现dos2unix的关键就是把dos中多余的 去掉。
sed 's/ //g' expressdos >expressdos1
模拟unix2dos:
sed 's/$/ /' expressdos > expressdos1
或
sed 's/$/x0d/' expressdos >expressdos1
awk 'gsub(/ /,""){print $0}' express > express2
gsub(r,s,t):在字符串t中用字符串s和正则表达式r匹配的所有字符串替换。返回值是替换的个数。如果没有给出t,默认是$0
相关解释:
使用gsub把 替换成"",然后再输出当前处理的整行字符串
-
将所有good改为bad并打印且只打印该行
sed -n ‘s/good/bad/g p’ express
awk 'gsub("good","bad"){print $0}' express
-
将包含is的行的good改为bad并打印且只打印该行
sed -n '/is/{/good/{s/good/bad/g;p}}' express
-n:安静模式,取消默认输出。
g:表示行内全面替换,当前处理行进行全局替换。
-n使用安静模式,/is/匹配包含is的行,/good/匹配包含is的行中包含good的行,s/good/bad/g,把改行所有的good都替换成bad,然后使用p输出该行。
awk '{if ($0~/is/ && $0~/good/) {gsub(“good”,"bad"); print $0}}' express
$0~/is/表示使用第0个域匹配/is/正则表达式,第0个域保存的即是当前处理的整行数据。
($0~/is/ && $0~/good/)就是如果当前处理的整行同时包含is和good的话就执行if里面的语句。if里面的语句使用gsub把匹配的good替换成bad,然后输出当前行。
-
将不包含is的行的good改为bad并打印且只打印该行
sed -n ‘/is/! {/good/{s/good/bad/g;p}}’ express
awk '{if ($0!~/is/ && $0~/good/) {gsub(/good/,"bad"); print $0}}' express
-
显示文件中的前10行(模拟“head” )
sed 10q express
q表示退出sed,10q表示处理到第10行的时候退出sed。
awk '{if (NR<11) print $0}' express
NR:表示awk开始执行程序后所读取的数据行数
-
在每5行后增加一空白行
sed 'n;n;n;n;G' express
n :读取下一个输入行,用下一个命令处理新的行而不是用第个命令。
G:获得内存缓冲区(hold space)的内容,并追加到当前模式空间文本的后面。
n;n;n;n;G的执行4个n命令读取下一行,每次读取之前都先输出当前的处理行。然后把hold space(这时为空)中的内容追加到模式空间的后面,相当于增加一空白行。
awk '{if (NR%5!=0) print $0;else printf("%s ",$0)}' express
-
倒置所有行,第一行成为最后一行,依次类推(模拟“tac”)
关于tac命令:
把文件内容反过来显示,文件内容的最后一行先显示,第一行最后显示。
sed '1!G;h;$!d' express
G:获得内存缓冲区的内容,并追加到当前模板块文本的后面。
h:拷贝模板块的内容到内存中的缓冲区。
d :从模板块(Pattern space)位置删除行。
!:表示后面的命令对所有没有被选定的行发生作用。
$:锚定行的结束如:/sed$/匹配所有以sed结尾的行。这里表示文件最后一行。
1:表示文件第一行
第一行的时候
1!G:在处理第一行的时候不把缓冲内容添加到当前处理行的末尾(因为你处理第一行的时候,缓冲还为空呢)
h:这个时候把第一行的内容(1)放到缓冲区
$!d:因为不是最后一行,所以删除,不打印出来
第二行的时候
1!G:此时1!G成立,把上一次保存的缓冲区内容(1)放到当前行(2)的末尾,第二行变成了(21)
h:这个时候把第二行的内容(21)放到缓冲区
$!d:因为不是最后一行,所以删除,不打印出来
第三行的时候
1!G:因为是第三行,所以1!G成立,则把上一次(第二行)保存的缓冲区内容(21)放到当前行(3)的末尾,第二行变成了(321)
h:这个时候把第三行的内容(321)放到缓冲区
$!d:因为不是最后一行,所以删除,不打印出来
这样直到处理到最后一行的时候:
1!G:此时1!G成立,把上(n-1)一次保存的缓冲区内容([n-1]…321)放到当前行(n)的末尾,该行变成了(n…321)
h:这个时候把第n行的内容(n…321)放到缓冲区
$!d:因为是最后一行,所以不删除,打印出第六行内容n[n-1]…321
awk '{A[i++]=$0}END{for(j=i-1;j>=0;j--)print A[j]}' express
BEGIN和END
在awk 中两个特别的表达式,BEGIN和END,这两者都可用于pattern中,提供BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。任何在BEGIN之后列出的操作(在{}内)将在awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。
首先输入每行字都执行A[i++]=$0,即是把所有行的内容保存到A[i]数组中。直到处理完所有的行之后,继续质询END中的内容:for(j=i-1;j>=0;j--)print A[j],这里是吧A[i]中的元素倒序输出,即是倒置所有的行。
-
显示文件中的最后10行(模拟“tail”)
sed方法:
sed -e :a -e '$q;N;11,$D;ba' express
sed方法相关命令参数:
-e
直接在指令列模式上进行sed 的动作编辑,允许多台编辑。
:a
表示建立一个标签a
b
跳转命令,这个命令是无条件跳转
ba表示跳转到标签a处
q
退出Sed。
N
追加下一个输入行到模板块后面并在二者间嵌入一个“ ”,改变当前行号码。
D
删除模板块的第一行。
11
表示文件第十一行
相关解释9:
首先创建一个a标签,然后不断执行这段代码:$q;N;11,$D;ba,如果是最后一行则退出sed,否则继续循环,N读取下一行,读取模式空间的第11行,如果是最后一行则删除模式空间的第一行,继续跳到标签a处执行。
awk方法:
awk '{a[i++]=$0}END{if (i>10) for (j=i-10;j<i;j++) print a[j];else for (j=0;j<i;j++)print a[j]}' express
相关解释:
使用{a[i++]=$0}把每行字符串赋给a[i]数组,然后判断数组大小是不是大于10 if (i>10),如果是则输入最后10个元素,否则直接输出所有的元素。
-
显示文件中的最后2行(模拟“tail -2”命令)
关于tail命令:
tail [ -r ] [ -n Number ] [ File ]
tail 命令从指定点开始将File 参数指定的文件写到标准输出。如果没有指定文件,则会使用标准输入。Number 变量
指定将多少单元写入标准输出。Number 变量的值可以是正的或负的整数。如果值的前面有+(加号),从文件开头
指定的单元数开始将文件写到标准输出。如果值的前面有-(减号),则从文件末尾指定的单元数开始将文件写到
标准输出。如果值前面没有+(加号)或-(减号),那么从文件末尾指定的单元号开始读取文件。
tail -2即是输出最后两行。
sed方法:
sed '$!N;$!D' express
sed相关命令参数:
!
表示后面的命令对所有没有被选定的行发生作用。
N
追加下一个输入行到模板块后面并在二者间嵌入一个“ ”,改变当前行号码。
D
删除模板块的第一行。
相关解释:
$!表示如果不是最后一行则执行N命令追加下一行,$!D表示如果不是最后一行则删除第一行。注意:执行D命令之后,pattern space 内不添加下一笔数据, 而将剩下的数据重新执行sedscript 。也就是直接再次执行$!N命令,读入下一行。知道最后一行时就不执行D删除命令,此时patten space中有最后两行数据。
awk方法:
awk '{a[i++]=$0}END{if (i>2) for (j=i-2;j<i;j++) print a[j];else for (j=0;j<i;j++)print a[j]}' express
相关解释:
a[i++]=$0命令保存所有行到a[i]数组中。处理完所有语句之后执行END里的内容。然后分两种情况输出:超过两条语句的使用a[i]数组输出最后两行,没有超过两句的,直接使用a[i]输出。
-
显示文件中的最后一行(模拟“tail -1”)
sed 'N;D' express
注意:执行D命令之后,pattern space 内不添加下一笔数据, 而将剩下的数据重新执行sedscript 。也就是直接再次执行N命令,读入下一行,然后删除第一行。一直这样循环,直到最后一行,打印输出patten space中的内容,也就是最后一行的内容
-
显示第9行
sed -n '9p' express
awk '{if (NR==9) print $0}' express
-
显示包含50个或以上字符的行
sed -n '/^.{50,}$/p' express
'/^.{50,}$/p' 表示匹配以非换行字符开始的50个以上的字符的行,然后使用p命令输出。
awk '{if (length($0)>=50) print $0}' express
-
显示部分文本——从包含apple的行开始到最后一行结束
sed -n '/apple/,$p' express
awk 'BEGIN{p=1}{if ($0~/apple/ || p==0){p=0;print $0}}' express
-
显示通篇文档,除了从包含apple的行到包含google的行
sed '/apple/,/google/d' express
/apple/,/google/d表示匹配从包含apple的行到包含google的行,然后使用d全部删除。
awk 'BEGIN{p=1}{if ($0!~/apple/ && p==1)print $0;else p=0;if ($0~/google/) p=1;}' express
首先在BEGIN中给p赋初值1,然后依次处理每一条语句。如果没有匹配到apple并且p==1,则输出改行;否则p=0,直到匹配到google为止,才让p=1,继续输出
三shell部分
-
编写一个名为nf的程序,显示当前目录中的文件数。键入程序并测试。
ls | awk ‘{files++} END {print files}’
BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。
END:让用户在最后一条输入记录被读取之后发生的动作。
-
编写一个名为whos的程序,显示排好序的已登录用户清单。只显示用户名,不要有其他信息。键入程序并测试。
who | sort -nrk1 | awk '{print $1}'
who 显示当前登录系统用户的信息
-n按照数字方式排序。
-r 颠倒指定排序的顺序。
-k作用是根据某个列来排序,默认是第1列(从1开始)。
54.在终端上显示
<<< echo $x >>> displays the value of x,which is $x
显示的时候,第2个$x的值应该被替换,比如如果x=3,显示:
<<< echo $x >>> displays the value of x,which is 3
X=3
echo "<<< echo $x >>> displays the value of x,which is $x"
55.依次执行下面三条命令,分析结果。
filename=/home/zsh/express
filename=$(echo $filename | tr “$(echo $filename | cut –cl)” “^”)
echo filename
如果是echo $filename则输出结果:^home^zsh^express
但是这里filename只是一个字符串,所以echo filename就只是输出filename这个字符串
-c1表示取出第一个字符
$(echo $filename | cut –cl) 表示取文件名的第一个字符的值,即“/”
tr “$(echo $filename | cut –cl)” “^” 表示把每一个“/”都替换成“^”
shell编程里的$(…)结构是什么作用,举例说明。
-
编写一脚本,打印出所有的参数。
#!/bin/sh
echo they are $*
exit 0
#! /bin/sh 是指此脚本使用/bin/sh来解释执行,#!是特殊的表示符,其后面跟的是解释此脚本的shell的路径)如果没有声明,则脚本将在默认的shell中执行,默认shell是由用户所在的系统定义为执行shell脚本的shell.
-
编写一个脚本,统计参数的总数。
#!/bin/sh
echo "$#"
exit 0
-
编写一个脚本,判断指定的文件是否存在
if [ ! -e “$1” ] ;then
echo “$1 do not exist”
fi
-e 当指定的文件或目录存在时返回真
#"["和"!"中间要有空格,"”"和"]"中间要有空格,";"和"then"中间有空格
60. 编写一个名为rename的程序,给第1个参数所给定的文件更名,在原名后添加第2个参数包含的一串字符。即
rename memol .sv
应该将文件memol更名为memol.sv
创建一个rename的文件,在里面编写:
mv $1 $1$2
mv $1 $1$2,中$1对应第一个参数,$2对应第二个参数,即是把$1对应的文件名更改为由$1$2组成的文件名
61.编写一个名为unrename的程序,从第1个参数指定的文件名的后部去掉第2个参数包含的字符串,即
unrename memol.sv .sv
应该把文件memol.sv更名为memol。要保证从尾部去掉字符串,如
unrename test1test test
应该将tes1test更名为test1(提示:用sed和命令替换)
mv $1 $(echo $1 | sed "s/$2$//")
$2$表示匹配第二个域的内容直到结尾的
$有点问题
-
编写一个shell脚本,使用循环语句将当前目录下的.c文件更名为.cpp.
解决方法:
for loop in $(ls)
do
if echo "$loop" | grep -q '.c'
then
mv $loop $(echo $loop | sed "s/.c$/.cpp/")
fi
done
关于shell脚本的for循环语句格式:
for循环语句格式如下:
for 变量名in 取值列表
do
命令列表
done
相关解释:
for loop in $(ls)表示变量loop从ls命令得到的列表中取值。
if echo "$loop" | grep -q '.c'中-q或--quiet或--silent 表示不显示任何信息。整句表示判断是否找到以.c结尾的文件,找到则执行then里面的语句。
mv $loop $(echo $loop|sed "s/.c$/.cpp/")表示把.c换成.cpp
-
source命令和exec命令有啥区别?举例说明。
exec和source都属于bash内部命令(builtins commands),在bash下输入man exec或man source可以查看所有的内部命令信息。
shell的内建命令exec将并不启动新的shell,而是用要被执行命令替换当前的shell进程,并且将老进程的环境清理掉,而且exec命令后的其它命令将不再执行
source命令或者".",不会为脚本新建shell,而只是将脚本包含的命令在当前shell执行。
不过,要注意一个例外,当exec命令来对文件描述符操作的时候,就不会替换shell,而且操作完成后,还会继续执行接下来的命令。
shell的内建命令exec将并不启动新的shell,而是用要被执行命令替换当前的shell进程,并且将老进程的环境清理掉,而且exec命令后的其它命令将不再执行。
因此,如果你在一个shell里面,执行exec ls那么,当列出了当前目录后,这个shell就自己退出了,因为这个shell进程已被替换为仅仅执行ls命令的一个进程,执行结束自然也就退出了。为了避免这个影响我们的使用,一般将exec命令放到一个shell脚本里面,用主脚本调用这个脚本,调用点处可以用bash a.sh,(a.sh就是存放该命令的脚本),这样会为a.sh建立一个sub shell去执行,当执行到exec后,该子脚本进程就被替换成了相应的exec的命令。
source命令或者".",不会为脚本新建shell,而只是将脚本包含的命令在当前shell执行。
解释下面的shell脚本
64 :
#!/bin/sh
rm -f fred
if [ -f fred ]; then
:
else
echo file fred does not exist
fi
exit 0
65:
#!/bin/sh
echo The date is $(date)
set $(date) #set什么意思?
echo The month is $2
exit 0
66:
#!/bin/sh
while [ "$1" != "" ]; do
echo "$1"
shift
done
exit 0
67:
#!/bin/bash
# Write a shell script that counts English language articles (a, an, the)
# in a given text file.
#
# --------------------------------------------------------------------
# This is a free shell script under GNU GPL version 2.0 or above
# Copyright (C) 2005 nixCraft project.
# Feedback/comment/suggestions : http://cyberciti.biz/fb/
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# -------------------------------------------------------------------------
echo -n "Enter a file name : " //参数-n的作用是不换行,echo默认是换行
read file //从键盘输入.read命令接收标准输入(键盘)的输入,或其他文件描述符的输入
a=0
the=0
an=0
# make sure file exist
if [ ! -f $file ] //-f filename 如果filename为常规文件,则为真
then
echo "$file not a file!"
exit 1 //exit(1)表示异常退出
fi
# put while loop to read a $file
while read line //读取文件$file每行直至文件尾结束
do
#process each word
for w in $line //变量w $line取值空间
do
# convert word to lowercase; so that we can count ThE, THE, the, THe etc all
lword="$(echo $w | tr '[A-Z]' '[a-z]')" //把每个字符都转成小写
# is it 'a' article?
[[ $lword = "a" ]] && (( a++ )) || [[ $lword = "the" ]] && (( the++ )) || [[ $lword = "an" ]] && (( an++ )) //统计a the an 的数量,分别保存在a,the和an中
done
done < $file
# display stats //输出2
echo "a article occured $a times"
echo "the article occured $the times"
echo "an article occured $an times"
68:
#!/bin/bash
#同步某个文件夹,使目的文件夹的内容和源文件夹的内容保持一致,如果源文件夹的某个文件作了更新,就将其拷贝进目的文件夹,如果源文件夹的某个文件已经删除,也将目的文件夹中相应的文件删除。
sync()
{
#检查使用方法是否正确
if [ $# -ne 2 ] // $# 表示提供到shell脚本或者函数的参数总数,-ne 表示不等于
then
echo "usage: ./sync src dst"
fi
#检查源文件夹是否存在
if [ ! -e $1 ] //-e $1 第一个参数所指的文件夹存在!非
then
echo "error : src don't exist"
exit 1
fi
#检查目的文件夹是否存在,如果不在,复制整个文件夹
if [ ! -e $2 ]
then
echo "cp -a $1 $2"
cp -a $1 $2 // -a 相当于-pdr ,-p保留源文件或目录的属性,-d若来源文件//为连结文件的属性(link file),则复制连结文件属性而非档案本身, -r 递归处理,将指定目//录下的文件与子目录一并处理
return 0
fi
#删掉目的文件夹多出的文件。
for Loop in $(ls $2)
do
if [ ! -e "$1/$Loop" ] //如果不存在这个文件$1/$Loop
then
echo "rm -fr $2/$Loop"
rm -fr "$2/$Loop" //-f 强制-r 递归删除目录和内容
fi
done
#循环处理当前源文件目录下的每个文件。
for Loop in $(ls $1)
do
#如果某个源文件对应的目的文件不存在,拷贝进目的文件夹。
if [ ! -e $2/$Loop ] //如果不存在这个文件$2/$Loop
then
echo " cp loop $1/$Loop $2/$Loop"
cp -a $1/$Loop $2/$Loop //复制一份$1/$Loop到$2/$Loop
Continue //进行下次循环,即继续找有没有这种文件
fi
#如果不是目录,是文件,检查是否更新,如果有,将其拷贝进目的文件。
if [ -f $1/$Loop ] //-f filename 如果filename为常规文件,则为真
then
#time1表示源文件的修改时间,time2表示目的文件的修改时间,如果time1大于time2,表示原文件被更新了。
//stat 显示文件的详细信息
//grep -i 不区分大小写
//cut
-c :以字符为单位进行分割,9-12
表示第9个字符到第12个字符
//-gt:大于
time1=$(stat $1/$Loop | grep -i 'modify' | cut -c 9-12,14,15,17,18,20,21,23,24,26,27)
time2=$(stat $2/$Loop | grep -i 'modify' | cut -c 9-12,14,15,17,18,20,21,23,24,26,27)
if [ $time1 -gt $time2 ] //-gt:大于
then
echo " cp $1/$Loop $2/$Loop"
cp $1/$Loop $2/$Loop
fi
continue
fi
#如果是目录,递归调用sync函数处理。
if [ -d $1/$Loop ] //-d 如果为目录,则为真
then
sync $1/$Loop $2/$Loop // sync()函数
fi
done
}
sync $1 $2 //sync()函数
exit 0
四:make命令部分:
69 解释下面的makefile文件
a="hello world"
b=$(a)
c:=$(a)
a="good bye"
print:
@echo b= $(b) //echo前面的@符号的作用是禁止回显,直接输出//“goodbye”, 而不是输出 “ echo b=goodbye
goodbye ”
@echo c= $(c) //c是”hello world”,因为c是:=,所以他只会从他之前找a的值
70:解释下面的makefile文件
all: myapp //终极目标
“all”这个伪目标是所有目标的目标,其功能一般是编译所有的目标。
# Which compiler
CC = gcc //宏定义
# Where to install
INSTDIR = /usr/local/bin //宏定义 INSTDIR安装目录
# Where are include files kept
INCLUDE = . //宏定义,当前目录
# Options for development
CFLAGS = -g -Wall -ansi
//-g为了调试用的
# Options for release
# CFLAGS = -O -Wall -ansi
CFLAGS: 指定头文件(.h文件)的路径,如:CFLAGS=-I/usr/include -I/path/include。同样地,安装一个包时会在安装路径下建立一个include目录,当安装过程中出现问题时,试着把以前安装的包的include目录加入到该变量中来。
//-o output_filename,确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。
myapp: main.o 2.o 3.o //需要的文件
$(CC) -o myapp main.o 2.o 3.o
我们可以看到[.o]文件的字符串被重复了两次,如果我们的工程需要加入一个新的[.o]文件,那么我们需要在两个地方加(应该是三个地方,还有一个地方在clean中)。
main.o: main.c a.h //需要的文件
$(CC) -I$(INCLUDE) $(CFLAGS) -c main.c
首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File,这个动作叫做编译(compile)。然后再把大量的Object File合成执行文件,这个动作叫作链接(link)。
target
... : prerequisites ...
command
...
...
target也就是一个目标文件,可以是Object
File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。
prerequisites就是,要生成那个target所需要的文件或是目标。
command也就是make需要执行的命令。(任意的Shell命令)
//-Ixxx 的意思是除了默认的头文件搜索路径(比如/usr/include等)外,同时还在路径xxx下搜索需要被引用的头文件。
//-c 表示只编译不链接,生成.o但不生成可执行文件
2.o: 2.c a.h b.h //需要的文件
$(CC) -I$(INCLUDE) $(CFLAGS) -c 2.c
3.o: 3.c b.h c.h //需要的文件
$(CC) -I$(INCLUDE) $(CFLAGS) -c 3.c
clean不是一个文件,它只不过是一个动作名字,有点像C语言中的lable一样,其冒号后什么也没有,那 么,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令。要执行其后的命令,就要在make命令后明显得指出这个lable的名字。 这样的方法非常有用,我们可以在一个makefile中定义不用的编译或是和编译无关的命令,比如程序的打包,程序的备份,等等。
clean:
-rm main.o 2.o 3.o //删除
“clean”这个伪目标功能是删除所有被make创建的文件。
install: myapp
@if [ -d $(INSTDIR) ]; //-d 是否为目录
“install”这个伪目标功能是安装已编译好的程序,其实就是把目标执行文件拷贝到指定的目标中去。
then
cp myapp $(INSTDIR); //复制mycpp到$(INSTDIR)
chmod a+x $(INSTDIR)/myapp;
//修改$(INSTDIR)/myapp的权限;a+x表示档案拥有者、群组、其他都增加了可执行的权限。
chmod og-w $(INSTDIR)/myapp;
//g表示与该档案的拥有者属于同一个群体(group)者,o表示其他以外的人,-w表示减少写//的权限。
echo "Installed in $(INSTDIR)";
else
echo "Sorry, $(INSTDIR) does not exist";
fi
五:iptables部分
-t指定表 -A追加规则 -s指定ip
-j进行处理动作 -D删除规则 -p指定ip协议
--dport目的端口 -F删除所有规则 -L列出所有规则
-i指定接收报文的接口名称 -d指定目标地址
解释下面命令
71:iptables -t filter -A INPUT -s 202.108.22.5 -j DROP
在指定表filter 追加一条Input规则指定ip为202.108.22.5 进行Drop处理动作
72:iptables -t filter -D INPUT -s 202.108.22.5 -j DROP
在指定表filter 删除指定指定ip为202.108.22.5 进行Drop处理动作
的INPUT规则
73:iptables -A INPUT -p tcp --dport 80 -j accept
追加Input规则定义过滤政策tcp 指定ip协议进行accept处理
--dport目的端口
74:iptables -F INPUT
删除INPUT上的所有规则
75:iptables -L INPUT
列出INPUT上的所有规则
76:iptable -A FORWARD -i eth1 -d 10.4.3.2 -j ACCEPT
追加一条FORWARD规则,eth1接口接收报文,目标地址为10.4.3.2,进行accept处理动作
注意: