第二章命令之乐cat 不仅可以读取文件并且连接数据,它还能从标准输入中进行读取要从标准输入中读取,就要使用管道操作符 echo 'Text through stdin' | cat - file.txt。这里的-被作为来之stdin 文本的文件名称实例 在file.txt 中写入dfagfmirgjriogjrogijdfgio后$ echo 'Text through stdin' | cat - file.txtText through stdindfagfmirgjriogjrogijdfgio$ echo 'Text through stdin' | cat < file.txtdfagfmirgjriogjrogijdfgio$ echo 'Text through stdin' | cat file.txtdfagfmirgjriogjrogijdfgiocat补充内容 -s, --squeeze-blank #压缩连续的空白行 suppress repeated empty output linestr -s, --squeeze-repeats#将多个连续的字符压缩成单个字符 replace each input sequence of a repeated character that is listed in SET1 with a single occurrence of that character如:file.txt 内容linelinelinelinelinelinelineline$ cat file.txt | tr -s '\n'linelinelinelinelinelinelinelinecat -n stream -n, --number #给内容之前加上行号 number all output lines录制与回放终端回话,很实用开始录制回话$ script -t 2>time.log -a output.sessionScript started, file is output.sessiontype commend.....exit两个配置文件被同时当做script命令的参数。其中一个文件(timing.log)用于存储时序信息,描述每一个命令在何时运行,另一个文件(output.session)用于存储命令输出,-t选项用于将时序数据导入stderr。2>则用于将stderr重定向到timeing.log。$ scriptreplay time.log output.session find文件查找-print 文件跟文件夹会以\n分隔find sourcedOf -iname "example" -print(忽略字母大小写)匹配多个find \( -name "*".txt -o -name "*.pdf" \) -print否定参数 !find . ! -name "*.txt" -print 不以.txt 结尾的-exec 结合多个命令-exec ./command.sh {} \;-exec printf "text file: %s\n" {} \;$ find . -exec printf "text file is: %s\n" {} \;text file is: .text file is: ./file.txttext file is: ./time.logtext file is: ./output.session玩转xargsxargs 也可以将单行或多行文本输入转换成其他格式,例如单行变多行或是多行变单行bash***都喜欢单行命令command | xargsxargs 是一种替换方式,类似与find命令的-exec参数实战演练1.将多行输入装换成单行输出cat file.txt | xargs line line line line line line line line2.将单行输入装换成多行输出指定每行最大值 -n max,每行max个参数,每个参数都是由" " 空格隔开的字符串。空格是默认的定界符cat file.txt | xargs -n 3line line lineline line lineline line更多xargs使用baidu 使用tr进行转换tr 可以进行替换,删除,压缩tr 只能通过stdin,而无法通过命令行参数来接受输入。他的调用格式如下tr [options] set1 set2echo "Hello who IS ThIs" | tr 'A-M,n-z' 'a-m,N-Z'hellO WhO iS ThiS使用tr删除字符tr -d 'set1' #只使用set1 ,而不使用set2echo "hello 0980world" | tr -d '0-9'hello world字符集的补集tr -c [set1] [set2] -c, -C, --complement 补数 use the complement of SET1zhangjianlin@zhangjianlin:~/mytest/linuxtest/linuxshellscrill/second$ echo -e "hello 0980world" | tr -d -c '0-9 \n' 0980zhangjianlin@zhangjianlin:~/mytest/linuxtest/linuxshellscrill/second$ echo -e "hello 0980world" | tr -d -c '0-9'算数运算echo {1..50} | echo $[ $( tr ' ' '+' ) 0 ] 1725$[ operation ] 执行算术运算相当于$[ 1+...+50+0 ]文件名的处理$name ${name%$1}$2 #${name%\.*} "%"号除去后缀名,只取文件名${file_name#*.} 只留扩展名或后缀校验和核实校验对与编写备份脚本或系统维护脚本来说都非常重要最知名且最为广泛的校验和技术是md5sum和shalsum实战演练计算md5sum,使用下面命令md5sum filename $ md5sum file.txt 221950d53cb7cc10da1c3e7e7ec4e0d5 file.txt $ md5sum file.txt > file.md5$ md5sum -c file.md5 file.txt: 确定sha1sum 跟 md5sum类似对目录进行校验校验和是从文件中计算得来的。对目录计算校验和意味着我们需要对目录中的所有文件以递归的方式进行计算它可以使用命令md5deep或sha1deep来实现md5deep -rl directory_path >directory.md5#-r 使用递归的方式#-l 使用相对路径。默认md5会输出文件的绝对路径 用下面命令进行核实$ md5sum -c directory.md5批量重命名和移动批量重命名文件名称(包括后缀名)
#a!/bin/bashfunctionlistfiles(){forfilein*; # * is all of pwd'filesdoecho$filedone}functioninputRule(){read-p "please input the fromsuffix as *.txt:"fromsuffix;read-p "please input the tosuffix as .txt:"tosuffix;read-p "please input the part of file name:"headname;}functionchangename(){count=1;forfromname in$fromsuffix;donew="${headname}${count}${tosuffix}"mv"$fromname""$new"2> /dev/null;if[ $? -eq0 ];thenecho"Renameing $fromname to $new";letcount++fidone}inputRule;changename;#listfiles;批量更改名称后缀,不包含名称
#!/bin/bashfunctioninputDialog(){read-p "input fromsuffix:"fromsuffixread-p "input tosuffix:"tosuffix}functionchangeSuffix(){forfromname in*${fromsuffix};do#echo $fromname \n#echo ${fromname%$fromsuffix}$tosuffixmv"$fromname""${fromname%$fromsuffix}$tosuffix"#不加""mv: 目标"*.png" 不是目录if[ $? -eq0 ];thenecho"$fromname"rename to "${fromname%$fromsuffix}$tosuffix"fidone}inputDialog;changeSuffix;
echo -e "\e[1;42m Green Background \e[0m" 彩色背景打印echo $var 或 echo ${var}var=value 一个赋值var = value 一个相等操作
赋值时双引号的使用(value是否包含空格)若无空格,特殊字符,加不加无所谓如:var=value 或 var="value"
但var="value cat" 必须加""length=${#var}获取变量值的长度如:zhangjianlin@zhangjianlin:~$ echo ${#PATH}288算数运算zhangjianlin@zhangjianlin:~/mytest/linuxtest/linuxshell$ echo "4 * 0.56" | bc2.24数组array_var=(1212 1233 424 565)#!/bin/basharray_var=(1212 3434 546 7687)echo ${array_var[*]} {}命令块,能执行命令,处理特殊字符echo ${#array_var[*]} #4
#!/bin/basharray_var=(1212 3434 546 7687)echo ${array_var[*]}echo ${#array_var[*]}alias rmback='cp $@ ~/backup; rm $@' 删除时备份
终端工具tput和stty是两款终端处理工具tput cols,lines,longname,cpu 100 100,输入密码时,不能让输入的内容显示出来。用stty
#!/bin/bash#Filename:password.shfunction enterpassword(){echo -e "Enter password"stty -echoread passwordstty echoecho password read}enterpassword
在脚本中生成延时
#!/bin/bash#Filename: sleep.shfunction delaytime(){echo -n Count:tput sc #store cursorcount=0;while true;doif [ $count -lt 40 ];then let count++;sleep 1;tput rc #recover cursortput ed #clear the content from the head to tail of cursorecho -n $count;else exit 0;fidone}delaytime;
递归函数bash同样支持递归函数F(){echo $1;F hello;sleep 1;}Fork×××":(){ :|:& };:"这个递归能调用自身,不断产生新的进程 :勿用利用子shell 生成一个独立进程#!/bin/bashpwd(cd /bin; ls);pwd通过引用子shell的方式保留空格和换行符假设我们使用子shell或反引号的方法将命令的输出读入一个变量中,可以将它放入双引号中,以保留空格和换行符(\n)out="$(cat text.txt)" 保留空格跟换行符号out=$(cat text.txt)用不回显的方式读取密码readread -s var在特定时限内读取输入read -t 2 varread -t 2 -s var
使用定界符结束输入,不使用Enter结束输入read -d ":" var 达到能输入换行的母的zhangjianlin@zhangjianlin:~/mytest/linuxtest/linuxshellscrill/first$ read -d ":" vardfdufdiffdfidjfgfgig:考虑CSV的数据情况#!/bin/bashfunction changeIFS(){oldIFS=$IFS #IFS的默认值是空白字符(换行符,制表符或者空格)IFS=,for item in $data;doecho item: $itemdoneIFS=$oldIFS}data="name,sex,rollno,location" #使用IFS读取变量的每一个条目 changeIFS;
#IFS默认空格,这里把他变成","
输出结果item: nameitem: sexitem: rollnoitem: location实战演练#!/bash/bin#user of shellfunction usesh(){oldIFS=$IFS;IFS=":";count=0;for item in $line;do[ $count -eq 0 ] && user=$item;[ $count -eq 6 ] && shell=$item;let count++;doneIFS=$oldIFS}line="root:x:0:0:root:root:/bin/bash"usesh;echo $user\'s shell is $shell
for循环for var in listdoconmenddoneecho {1..30};echo {a..z};echo {A..Z};echo {a..h};for i in {a..z};docommenddonefor((i=0;i<10;i++)){ commend}比较与测试逻辑运算将它变得简洁[ condition ] && action; 如果是真执行action[ condition ] || action; 如果是假真执行action算术比较(数字比较)[ $var -eq 0 ] or [ $var -ne 0 ]其他的操作符-gt 大于-lt 小于-ge 大于或等于le 小于或等于-eq 等于文件相关的测试[ -f $file_var ] 是否是文件-x 可执行-d 目录-e存在-c 字符设备路径-b 块设备-w 文件可写-r 文件是否可读-L 符号连接
判断输入的是否为文件或文件夹
#!/bin/bashfunctionfileordir(){if[ -e $fpath ];then# existif[ -d $fpath ] ;then#directoryecho$fpath is a dir;exitfiif[ -f $fpath ] ;thenecho$fpath is a file;exitfielseecho-e "$fpath not exit";exit;fiecho"unknow file type"}fpath=$1fileordir;
zhangjianlin@zhangjianlin:~/mytest/linuxtest/linuxshellscrill/first$ bash filetest.sh .
字符串比较使用字符串比较时,最好用双括号,因为有时候采用单引号会产生错误,所以最好避开他们。[[ $str1 == $str2 ]][[ $str1 != $str2 ]][[ $str1 > $str2 ]][[ $str1 < $str2 ]][[ $str1 -z $str2 ]] 空字窜[[ $str1 -n $str2 ]] 非空字窜if [[ $str1 < $str2 ]] && [[ $str1 == $str2 ]]test命令执行条件检测test有助于避免使用过多的括号之前的[]测试条件同样可以用于test命令if [ $var -eq 0 ];then echo "True";fiif test $var -eq 0 ;then echo "True";fi
第二章命令之乐cat 不仅可以读取文件并且连接数据,它还能从标准输入中进行读取要从标准输入中读取,就要使用管道操作符 echo 'Text through stdin' | cat - file.txt。这里的-被作为来之stdin 文本的文件名称实例 在file.txt 中写入dfagfmirgjriogjrogijdfgio后$ echo 'Text through stdin' | cat - file.txtText through stdindfagfmirgjriogjrogijdfgio$ echo 'Text through stdin' | cat < file.txtdfagfmirgjriogjrogijdfgio$ echo 'Text through stdin' | cat file.txtdfagfmirgjriogjrogijdfgiocat补充内容 -s, --squeeze-blank #压缩连续的空白行 suppress repeated empty output linestr -s, --squeeze-repeats#将多个连续的字符压缩成单个字符 replace each input sequence of a repeated character that is listed in SET1 with a single occurrence of that character如:file.txt 内容linelinelinelinelinelinelineline$ cat file.txt | tr -s '\n'linelinelinelinelinelinelinelinecat -n stream -n, --number #给内容之前加上行号 number all output lines录制与回放终端回话,很实用开始录制回话$ script -t 2>time.log -a output.sessionScript started, file is output.sessiontype commend.....exit两个配置文件被同时当做script命令的参数。其中一个文件(timing.log)用于存储时序信息,描述每一个命令在何时运行,另一个文件(output.session)用于存储命令输出,-t选项用于将时序数据导入stderr。2>则用于将stderr重定向到timeing.log。$ scriptreplay time.log output.session find文件查找-print 文件跟文件夹会以\n分隔find sourcedOf -iname "example" -print(忽略字母大小写)匹配多个find \( -name "*".txt -o -name "*.pdf" \) -print否定参数 !find . ! -name "*.txt" -print 不以.txt 结尾的-exec 结合多个命令-exec ./command.sh {} \;-exec printf "text file: %s\n" {} \;$ find . -exec printf "text file is: %s\n" {} \;text file is: .text file is: ./file.txttext file is: ./time.logtext file is: ./output.session玩转xargsxargs 也可以将单行或多行文本输入转换成其他格式,例如单行变多行或是多行变单行bash***都喜欢单行命令command | xargsxargs 是一种替换方式,类似与find命令的-exec参数实战演练1.将多行输入装换成单行输出cat file.txt | xargs line line line line line line line line2.将单行输入装换成多行输出指定每行最大值 -n max,每行max个参数,每个参数都是由" " 空格隔开的字符串。空格是默认的定界符cat file.txt | xargs -n 3line line lineline line lineline line更多xargs使用baidu 使用tr进行转换tr 可以进行替换,删除,压缩tr 只能通过stdin,而无法通过命令行参数来接受输入。他的调用格式如下tr [options] set1 set2echo "Hello who IS ThIs" | tr 'A-M,n-z' 'a-m,N-Z'hellO WhO iS ThiS使用tr删除字符tr -d 'set1' #只使用set1 ,而不使用set2echo "hello 0980world" | tr -d '0-9'hello world字符集的补集tr -c [set1] [set2] -c, -C, --complement 补数 use the complement of SET1zhangjianlin@zhangjianlin:~/mytest/linuxtest/linuxshellscrill/second$ echo -e "hello 0980world" | tr -d -c '0-9 \n' 0980zhangjianlin@zhangjianlin:~/mytest/linuxtest/linuxshellscrill/second$ echo -e "hello 0980world" | tr -d -c '0-9'算数运算echo {1..50} | echo $[ $( tr ' ' '+' ) 0 ] 1725$[ operation ] 执行算术运算相当于$[ 1+...+50+0 ]文件名的处理$name ${name%$1}$2 #${name%\.*} "%"号除去后缀名,只取文件名${file_name#*.} 只留扩展名或后缀校验和核实校验对与编写备份脚本或系统维护脚本来说都非常重要最知名且最为广泛的校验和技术是md5sum和shalsum实战演练计算md5sum,使用下面命令md5sum filename $ md5sum file.txt 221950d53cb7cc10da1c3e7e7ec4e0d5 file.txt $ md5sum file.txt > file.md5$ md5sum -c file.md5 file.txt: 确定sha1sum 跟 md5sum类似对目录进行校验校验和是从文件中计算得来的。对目录计算校验和意味着我们需要对目录中的所有文件以递归的方式进行计算它可以使用命令md5deep或sha1deep来实现md5deep -rl directory_path >directory.md5#-r 使用递归的方式#-l 使用相对路径。默认md5会输出文件的绝对路径 用下面命令进行核实$ md5sum -c directory.md5批量重命名和移动批量重命名文件名称(包括后缀名)
#a!/bin/bashfunctionlistfiles(){forfilein*; # * is all of pwd'filesdoecho$filedone}functioninputRule(){read-p "please input the fromsuffix as *.txt:"fromsuffix;read-p "please input the tosuffix as .txt:"tosuffix;read-p "please input the part of file name:"headname;}functionchangename(){count=1;forfromname in$fromsuffix;donew="${headname}${count}${tosuffix}"mv"$fromname""$new"2> /dev/null;if[ $? -eq0 ];thenecho"Renameing $fromname to $new";letcount++fidone}inputRule;changename;#listfiles;批量更改名称后缀,不包含名称
#!/bin/bashfunctioninputDialog(){read-p "input fromsuffix:"fromsuffixread-p "input tosuffix:"tosuffix}functionchangeSuffix(){forfromname in*${fromsuffix};do#echo $fromname \n#echo ${fromname%$fromsuffix}$tosuffixmv"$fromname""${fromname%$fromsuffix}$tosuffix"#不加""mv: 目标"*.png" 不是目录if[ $? -eq0 ];thenecho"$fromname"rename to "${fromname%$fromsuffix}$tosuffix"fidone}inputDialog;changeSuffix;