Linux Shell脚本攻略2:命令之乐(1)
2017-09-10 16:49
176 查看
用cat进行拼接
cat(concatenate)是命令行玩家首先必须学习的命令之一,它通常用于读取、显示或拼接文件内容,不过cat的能力远不止如此,它甚至可以一次性将来自stdin和文件的内容拼接到一起。$ cat file1 file2 file3 ... #将多个文件内容拼接在一起
cat不仅可以读取文件、拼接数据,还能够从标准输入中进行读取,从标准输入中读取需要使用管道操作符。
$ OUTPUT_FROM_SOME COMMANDS | cat
我们可以用cat将来自输入文件的内容与标准输入拼接在一起,将stdin和另一个文件中的数据结合起来。
$ echo 'Text through stdin' | cat - file.txt # - 被作为stdin文本的文件名
$ cat -s file# 删除额外的空白行(相邻的多个空白行只保留一个)。
$ cat -T file.py# 将制表符显示为^|。
$ cat -n lines.txt# 显示行号(包括空白行,如果想跳过空白行,可以使用选项
-b)。
录制并回放终端会话
# -t选项用于将时序数据导入stderr,2>用于将stderr重定向到timing.log,时序信息记录了每个命令在何时运行;output.session文件用于存储命令输出。 script -t 2> timing.log -a output.session type commands; ''' .. exit # scriptreplay用于回放,按播放命令序列输出 scriptreplay timing.log output.session
文件查找与文件列表
find是Unix/Linux命令行工具箱中最棒的工具之一。其工作方式为:沿着文件层次结构向下遍历,匹配符合条件的文件,执行相应的操作。$ find bash_path#列出当前目录及子目录下所有的文件和文件夹
如:
$find . -print#
.指定当前目录,
..指定父目录。
\n作为用于对输出的文件名进行分隔。就算忽略
-print0指明使用
\0作为匹配的文件名之间的定界符。当文件名中包含换行符时,这个方法就有用武之地了。
根据文件名或正则表达式进行搜索
$ find /home/slynux -name "*.txt" -print#选项
-name的参数制定了文件名所必须匹配的字符串,我们可以将通配符作为参数使用。
$ find . -iname "example*" -print#选项
-iname的作用和
-name类似,只不过在匹配名字时会忽略大小写。
$ find . \( -name "*.txt" -o -name "*.pdf" \) -print#匹配多个条件
$ find /home/users -path "*/slynux/*" -print#选项
-path的参数可以使用通配符来匹配文件路径。
-name总是用给定的文件名进行匹配,
-path则将文件路径作为一个整体进行匹配。
$ find . -regex ".*\(\.py|\.sh\)$"# 基于正则表达式来匹配文件路径
$ find . -iregex ".*\(\.py|\.sh\)$"# 忽略大小写。
否定参数。
find也可以用
!否定参数的含义,如:
$ find . ! -name "*.txt" -print#匹配所有不以
.txt结尾的文件名。
基于目录深度的搜索。find命令在使用时会遍历所有的子目录,我们可以采用深度选项
-maxdepth和
-mindepth来限制find命令遍历的目录深度。
大多数情况下,我们只需要在当前目录中进行搜索,无须再继续向下查找。如果只允许find在当前目录中查找,深度可以设置为1;当需要向下两级时,深度可以设置为2;依此类推。
$ find . -maxdepth 1 -name "f*" -print#只搜索当前目录
$ find . -mindepth 2 -name "f*" -print#从第二级目录开始搜索
根据文件类型搜索
$ find . -type d -print#只列出所有的目录
$ find . -type f -print#只列出普通文件
$ find . -type l -print#只列出符号链接
$ find . -type c -print#只列出字符设备
$ find . -type b -print#只列出块设备
$ find . -type s -print#只列出套接字
$ find . -type p -print#只列出FIFO
根据文件时间进行搜索
按天:访问时间
-atime;修改时间
-mtime;变化时间
-ctime
按分钟:访问时间
-amin;修改时间
-mmin;变化时间
-cmin
$ find . -type f -atime 7 -print#打印出恰好在7天前被访问过的所有文件
$ find . -type f -atime -7 -print#打印出在最近7天内被访问过的所有文件
$ find . -type f -atime +7 -print#打印出访问时间超过7天的所有文件
$ find . -type f -amin +7 -print#打印出访问时间超过7分钟的所有文件
$ find . -type f -newer file.txt -print#打印出比file.txt修改时间更近的所有文件
基于文件大小的搜索
$ find . -type f -size +2k#大于2KB的文件
$ find . -type f -size -2k#小于2KB的文件
$ find . -type f -size 2k#大小等于2KB的文件
除了k之外,还可以用其他文件大小单元。
b —— 块(512字节)
c —— 字节
w —— 字(2字节)
k —— 1024字节
M —— 1024K字节
G —— 1024M字节
删除匹配的文件
$ find . -type f -name "*.swp" -delete
基于文件权限和所有权的匹配
$ find . -type f -perm 644 -print#打印出权限为644的文件
$ find . -type f ! -perm 644 -print#打印出权限没有设置为644的文件
$ find . -type f -user slynux -print#打印出用户slynux拥有的所有文件
利用find执行命令或动作
find命令可以借助选项
-exec与其他命令进行结合,
-exec算的上是find最强大的特性之一。
$ find . -type f -user root -exec chown slynux {} \;#
{}是一个与
-exec选项搭配使用的特殊字符串。对于每一个匹配的文件,
{}会被替换成相应的文件名。
$ find . -type f -name "*.c" -exec cat {} \;>all_c_file.txt#将给定目录中所有C程序文件拼接起来写入单个文件
$ find . -type f -mtime +10 -name "*.txt" -exec cp {} OLD \;#将10天前的txt文件复制到OLD目录中。
$ find . -type f -name "*.txt" -exec printf "Text file: %s\n" {} \;#
-exec可以同
printf结合来生成有用的输出信息。
-exec无法结合多个命令,但是我们可以将多个命令写到一个shell脚本中(如command.sh),然后在
-exec中使用这个脚本:
-exec ./command.sh {} \;
让find跳过特定的目录。在搜索目录并执行某些操作时,有时为了提高性能,需要跳过一些子目录。
$ find devel/source_path \( -name ".git" -prune \) -o \( -type f-print \)#打印出不包括在
.git目录中的所有文件的名称。
玩转xargs
我们可以用管道将一个命令的stdout重定向到另一个命令的stdin,如:cat foo.txt | grep "test"。但是有些命令只能以命令行参数的形式接收数据,无法通过stdin接受数据流。
我们可以使用
xargs将标准输入数据转换为命令行参数;
xargs也可以将单行或多行文本输入转换成其他格式,例如单行变多行或是多行变单行。
xargs命令应该紧跟在管道操作符之后,以标准输入作为主要的源数据流。它使用stdin并通过提供命令行参数来执行其他命令。如:
command | xargs。
$ cat example.txt | xargs#单行输出
$ cat example.txt | xargs -n 3#每行最多3个参数,多行输出,参数间由空格隔开。
$ echo "splitXsplitXsplitXsplit" | xargs -d X#用
-d选项为输入指定一个定制的定界符。
$ echo "splitXsplitXsplitXsplit" | xargs -d X -n 2#结合
-d和
-n选项。
读取stdin,将格式化参数传递给命令。
#!/bin/bash # 文件名:cecho.sh echo $*'#'
有一个包含着参数列表的文件(每行一个参数),通过两种方法传递给一个命令(cecho.sh),第一种方法,每次提供一个参数,如:
./cecho.sh arg1 ./cecho.sh arg2 ./cecho.sh arg3
我们可以这样写:
$ cat args.txt | xargs -n 1 ./cecho.sh
第二种方法,一次性提供所有参数,如:
./cecho.sh arg1 arg2 arg3
有时我们还需要一些固定不变的命令参数,如:
./cecho.sh -p arg1 -l
xargs有一个选项
-I,可以提供上面这种形式的命令执行序列。我们可以通过
-I指定替换字符串,这个字符串在xargs扩展时会被替换掉,如果将
-I与xargs 结合使用,对于每个参数,命令都会被执行一次。如:
$ cat args.txt | xargs -I {} ./cecho.sh -p {} -l
结合find使用xargs。xargs和find是一对死党,但是人们通常却是以一种错误的组合方式使用他们。 如:
$ find . -type f -name "*.txt" -print | xargs rm -f。
这种做法很危险,因为我们无法预测分隔find命令输出结果的定界符究竟是什么(
\n或者),很多文件名可能包含空格,因此xargs可能会误认为它们是定界符,如
hell text.txt会被xargs误解为hell和text.txt。
只要我们把find的输出作为xargs的输入,就必须将
-print0与find结合使用,以字符
null(\0)来分隔输出。
$ find . -type f -name "*.txt" -print0 | xargs -0 rm -f#
xargs -0将
\0作为输入定界符。
统计源代码目录中所有C程序文件的行数。
$ find source_code_dir_path -type f -name "*.c" -print0 | xargs -0 wc -l
结合stdin,巧妙运用while语句和子shell。xargs只能以有限的几种方式来提供参数,而且它也不能为多组命令提供参数,要执行包含来自标准输入的多个参数的命令,有一种非常灵活的方法。包含while循环的子shell可以用来读取参数,然后通过一种巧妙的方式执行命令:
$ cat files.txt | ( while read arg; do cat $arg; done )
等同于
$ cat files.txt | xargs -I {} cat {}
在while循环中,我们可以将
cat $arg替换成任意数量的命令,这样我们就可以对同一个参数执行多条命令。也可以不借助管道,将输出传递给其他命令。这个技巧能够使用于各种问题场景,子shell操作符内部的多个命令可以作为一个整体来运行。
$ cmd0 | ( cmd1;cmd2;cmd3 ) | cmd4
相关文章推荐
- linux shell 脚本攻略学习16--wc命令详解,tree命令详解
- linux shell 脚本攻略学习19--sed命令详解
- Shell 命令--cut--总结自《Linux Shell 脚本攻略》
- Shell 命令--paste--总结自《Linux Shell 脚本攻略》
- linux shell 脚本攻略学习13--file命令详解,diff命令详解
- linux shell 脚本攻略学习11--mkdir和touch命令详解
- linux shell 脚本攻略学习13--file命令详解,diff命令详解
- linux shell 脚本攻略学习20--awk命令入门详解
- Shell 命令--网站--总结自《Linux Shell 脚本攻略》
- linux shell 脚本攻略学习7---tr命令详解
- Shell 命令--文件创建、搜索命令--总结自《Linux Shell 脚本攻略》
- Shell 命令--文件创建、搜索命令--总结自《Linux Shell 脚本攻略》
- linux shell 脚本攻略学习12--文件权限详解,chmod命令详解,chown命令详解,chattr命令详解
- linux shell 脚本攻略学习18--grep命令详解
- 【Linux Shell脚本攻略之一】find命令:文件查找和文件列表
- linux shell 脚本攻略学习8---md5校验,sort排序,uniq命令详解
- linux shell 脚本攻略学习9--rename命令详解
- Shell 命令--echo tr ls--总结自《Linux Shell 脚本攻略》
- Shell常识--基本函数和简单命令rev--总结自《Linux Shell 脚本攻略》
- Linux shell 脚本攻略 第二章 命令之乐