Shell脚本经典的用法
2010-09-06 09:43:55 阿炯

这里介绍一些shell脚本程序,很简短,只在命令行执行即可完成任务。

For循环的妙用
----------------------------------------------------
general syntax of 'for' loops

for variable in value list
do
     command1
     command2
     ......
done

variable is a character sequence that holds a value.
value list is a set of values that the variable can have.
command is set of instructions that are executed.

在一目录下查找特定文件中的特定字符,打印文件及匹配字串及其所在的行号。在目录"api.freeoa.net -name"下递归查找以php后缀的文件中包含有".local"字样的文件,打印出所在行号.
for i in `find api.freeoa.net -name "*.php" -type f -print`; do grep -n .local $i&&echo $i; done

----------------------------------------------------
将一个文件复制成多个复本.
for i in {1..40}; do echo $i && cp test.zip test.zip.$i; done

----------------------------------------------------
产生序列数.如生成1~100的数,然后可以让for来使用.
seq -f %g 1 12
printf '%d\n' {1..20}

整合了一个:
for i in $(printf '%d\n' {1..20}) ;do echo $i;done

----------------------------------------------------
列出当前目录下文件及其文件类型.
for i in $(ls); do echo -n $i && file $i; done

----------------------------------------------------
对当前目录的文档各个打包后在清除其
for i in $(ls); do tar -cvf $i.tar $i && rm -fv $i; done

----------------------------------------------------
debian下查找特定关键字文件的软件包并下载之.
for i in `apt-cache search nagios|awk -F ' - ' '{print($1)}'`; do echo $i && apt-get install -d -y $i; done

for i in `more nrpe_local.cfg |grep -v ^#|grep -v ^$|grep ^command|awk -F '=' '{print($2)}'|awk -F ' ' '{print($1)}'`; do echo $i; done

----------------------------------------------------
在当前目录下查找用变量$hto替换的文件名,并显示出其文件类型.
for i in $(find ./ -name "*$hto*" -mtime +30 -exec ls {} \;); do file $i ;done

for i in $(find . -maxdepth 1 -type f -iname "*.jpg" -exec basename '{}' \;); do
        echo "--- Start on $i ------"
        jpegtran -optimize -copy none -progressive -outfile $i original-$i
        echo "--- Done with $i ------"
done;

----------------------------------------------------
杀死一系统相关进程
for pid in $(ps aux | grep perl|grep -v grep | awk ' { print $2}');do echo "==================I will kill the $pid==========" && kill -9 $pid;done

----------------------------------------------------
批量导入导出若干个数据库
for i in $(ls); do echo -n import db $i && mysql -uplats -ppaswd<$i; done

for i in game ADStat sgs tra wiki; do echo  export db $i && mysqldump --databases $i  --flush-logs --user=root  --verbose --password='passwd' --opt>$i.sql; done

----------------------------------------------------
使用ImageMagick来转换照片
for i in $(ls); do echo -n 'convert photo: '  $i && convert <$i; done

----------------------------------------------------
在将项目上传到服务器的时候,忘记消除.svn 目录了。现在来介绍下在Linux下,利用shell命令来删除.svn目录:
find . -type d -name ".svn"|xargs rm -rfv

----------------------------------------------------
shell-can not execute binary file

在执行如下脚本:
su - user /usr/local/bin/my.sh

结果提示:
can not execute binary file

此种情形多发于在windows下编辑好脚本在上传到linux下会常发生这种情况。其原因是在脚本的第一行有问题,也即:
#!/bin/sh
这一句不干净,怎么不干净呢,当你用"od -c"来查看该脚本程序时,会发现“#!/bin/sh”前面还有一些字符,而正常情况下是不会有的!!处理掉这些多余符号再运行这些脚本就不会出错了。

----------------------------------------------------
批量杀死进程
杀死从cmd所起来的进程(通常是多个,单个进程的话在此无意义),pkill说不定会在没干完活之前把自己给kill了。
ps -ef | grep cmd | grep -v grep | awk '{print $2}' | xargs kill -9
ps aux|grep cmd|grep -v grep |perl -lane 'print $F[1]'|xargs kill -9

----------------------------------------------------
使用循环来实现批量操作:for、while、until

将当前目录下的.xml文件重命名为.txt:
for x in *.xml; do
  t=$(echo $x | sed 's/\.xml$/.txt/');
  mv $x $t && echo "moved $x -> $t"
done

更好操作方法(Bash Shell),用参数展开替换开启子shell的方式:
for x in *.xml; do
  t=${x%.xml}.txt
  mv $x $t && echo "moved $x -> $t"
done

如果要显示的文件中包括了空格,就需要将其用双引用引起来:
for i in $(ls); do echo "$i"; done;

或借用输入分隔符来操作:
or, you can change the input field separator (IFS) environment variable:
IFS=$'\n';for file in $(ls); do echo $i; done

这样操作也行:
for i in *; do echo "$i"; done;
for f in *; do echo "File -> $f"; done

看完了for语句,再来看看while语句

while true; do sth; done

while sleep 2; do echo thinking in freeoa; done

always "true":
while :; do foo; sleep 2; done

多行语句间使用分号隔开:
while [1]; do foo; sleep 2; done

如果可行还可以用until:
until ((0)); do echo date +%Y年%m月%d日%A%H:%M:%S; sleep 2; done

while read filename; do echo filename: "$filename"; done < filelist.txt
while read ps;do echo PS:$ps;done < ps.txt

注意,与while相反,until执行循环中的命令时,只要测试条件的退出状态不为零就会一直执行。

Using a while loop:
while read i; do foo; sleep 2; done < /dev/urandom

Using a for loop:
for ((;;)); do foo; sleep 1; done

Another way using until:
until [ ]; do foo; sleep 2; done

简单的无限循环...
while true ; do continue ; done

while true; do foo ; sleep 1 ; done

bash is particular about spaces in variable assignments. The shell has interpreted i = $i + 1 as a command i and the rest of them as arguments to i, that is why you see the errors is saying i is not installed.

使用算术运算符(Arithmetic Expression)

i=0; while [ $i -lt 9 ]; do echo "hi $i"; sleep 1; ((i++)); done

i=0; while [ $i -lt 9 ]; do echo "hi $i"; sleep 1; i=$(($i + 1)); done

可以在循环上下文中使用算术表达式

i=0;while((i++ < 9)); do echo hi $i; sleep 1; done

i=0; while[ $i -lt 9 ]; do echo "hi $i"; sleep 1; i=$(($i + 1)); done

POSIX-ly

i=0; while [ $i -lt 9 ]; do echo "hi $i"; sleep 1; i=$((i+1)); done

POSIX shell supports $(( )) to be used in a math context, meaning a context where the syntax and semantics of C's integer arithmetic are used.

for i in {1..5}; do some-cmds; done
OR
for((i=1;i<=10;i+=2)); do echo "Welcome $i times"; done

while :; do echo 'Hit CTRL+C'; sleep 1; done
OR
while true; do echo 'Hit CTRL+C'; sleep 1; done

----------------------------------------------------


该文章最后由 阿炯 于 2023-08-01 16:27:25 更新,目前是第 4 版。