昨天为了在一个目录下搜索文本文件的内容,发现ubuntu文件夹默认的搜索功能太简单了。要实现自定义搜索,还是得需要使用命令行。并且需要使用管道,xargs等“高级”指令
1、find命令
find命令是一个无处不在命令,是linux中最有用的命令之一。find命令用于:在一个目录(及子目录)中搜索文件,你可以指定一些匹配条件,如按文件名、文件类型、用户甚至是时间戳查找文件。下面就通过实例来体验下find命令的强大。
1.1、find命令的一般形式
man文档中给出的find命令的一般形式为:
find [-H] [-L] [-P] [-D debugopts] [-Olevel] [path...] [expression]
其实[-H] [-L] [-P] [-D debugopts] [-Olevel]这几个选项并不常用(至少在我的日常工作中,没有用到过),上面的find命令的常用形式可以简化为:
find [path...] [expression]
- path:find命令所查找的目录路径。例如用.来表示当前目录,用/来表示系统根目录
- expression:expression可以分为——“-options [-print -exec -ok ...]”
- -options,指定find命令的常用选项,下节详细介绍
- -print,find命令将匹配的文件输出到标准输出
- -exec,find命令对匹配的文件执行该参数所给出的shell命令。相应命令的形式为'command' { } \;,注意{ }和\;之间的空格
find ./ -size 0 -exec rm {} \; 删除文件大小为零的文件 (还可以以这样做:rm -i `find ./ -size 0` 或 find ./ -size 0 | xargs rm -f &)
为了用ls -l命令列出所匹配到的文件,可以把ls -l命令放在find命令的-exec选项中:find . -type f -exec ls -l { } \;
在/logs目录中查找更改时间在5日以前的文件并删除它们:find /logs -type f -mtime +5 -exec rm { } \; - -ok,和-exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的shell命令,在执行每一个命令之前,都会给出提示,让用户来确定是否执行。
find . -name "*.conf" -mtime +5 -ok rm { } \; 在当前目录中查找所有文件名以.LOG结尾、更改时间在5日以上的文件,并删除它们,只不过在删除之前先给出提示
也有人这样总结find命令的结构:
find start_directory test options criteria_to_match action_to_perform_on_results
1.2、find命令的常用选项及实例
- -name
按照文件名查找文件。
find /dir -name filename 在/dir目录及其子目录下面查找名字为filename的文件
find . -name "*.c" 在当前目录及其子目录(用“.”表示)中查找任何扩展名为“c”的文件 - -perm
按照文件权限来查找文件。
find . -perm 755 –print 在当前目录下查找文件权限位为755的文件,即文件属主可以读、写、执行,其他用户可以读、执行的文件 - -prune
使用这一选项可以使find命令不在当前指定的目录中查找,如果同时使用-depth选项,那么-prune将被find命令忽略。
find /apps -path "/apps/bin" -prune -o –print 在/apps目录下查找文件,但不希望在/apps/bin目录下查找
find /usr/sam -path "/usr/sam/dir1" -prune -o –print 在/usr/sam目录下查找不在dir1子目录之内的所有文件 - -user
按照文件属主来查找文件。
find ~ -user sam –print 在$HOME目录中查找文件属主为sam的文件 - -group
按照文件所属的组来查找文件。
find /apps -group gem –print 在/apps目录下查找属于gem用户组的文件 - -mtime -n +n
按照文件的更改时间来查找文件, - n表示文件更改时间距现在n天以内,+ n表示文件更改时间距现在n天以前。
find / -mtime -5 –print 在系统根目录下查找更改时间在5日以内的文件
find /var/adm -mtime +3 –print 在/var/adm目录下查找更改时间在3日以前的文件 - -nogroup
查找无有效所属组的文件,即该文件所属的组在/etc/groups中不存在。
find / –nogroup -print - -nouser
查找无有效属主的文件,即该文件的属主在/etc/passwd中不存在。
find /home -nouser –print - -newer file1 ! file2
查找更改时间比文件file1新但比文件file2旧的文件。 - -type
查找某一类型的文件,诸如:
b - 块设备文件。
d - 目录。
c - 字符设备文件。
p - 管道文件。
l - 符号链接文件。
f - 普通文件。
find /etc -type d –print 在/etc目录下查找所有的目录
find . ! -type d –print 在当前目录下查找除目录以外的所有类型的文件
find /etc -type l –print 在/etc目录下查找所有的符号链接文件 - -size n:[c] 查找文件长度为n块的文件,带有c时表示文件长度以字节计。
find . -size +1000000c –print 在当前目录下查找文件长度大于1 M字节的文件
find /home/apache -size 100c –print 在/home/apache目录下查找文件长度恰好为100字节的文件
find . -size +10 –print 在当前目录下查找长度超过10块的文件(一块等于512字节) - -depth:在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找。
find / -name "CON.FILE" -depth –print 它将首先匹配所有的文件然后再进入子目录中查找 - -mount:在查找文件时不跨越文件系统mount点。
find . -name "*.XC" -mount –print 从当前目录开始查找位于本文件系统中文件名以XC结尾的文件(不进入其他文件系统) - -follow:如果find命令遇到符号链接文件,就跟踪至链接所指向的文件。
1.3、find与xargs
在使用find命令的-exec选项处理匹配到的文件时, find命令将所有匹配到的文件一起传递给exec执行。但有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现 溢出错误。错误信息通常是“参数列太长”或“参数列溢出”。这就是xargs命令的用处所在,特别是与find命令一起使用。
find命令把匹配到的文件传递给xargs命令,而xargs命令每次只获取一部分文件而不是全部,不像-exec选项那样。这样它可以先处理最先获取的一部分文件,然后是下一批,并如此继续下去。
在有些系统中,使用-exec选项会为处理每一个匹配到的文件而发起一个相应的进程,并非将匹配到的文件全部作为参数一次执行;这样在有些情况下就会出现进程过多,系统性能下降的问题,因而效率不高;
而使用xargs命令则只有一个进程。另外,在使用xargs命令时,究竟是一次获取所有的参数,还是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内核中相应的可调参数来确定。
来看看xargs命令是如何同find命令一起使用的,并给出一些例子。
find . -type f -print | xargs file #查找系统中的每一个普通文件,然后使用xargs命令来测试它们分别属于哪类文件 find / -name "core" -print | xargs echo "" >/tmp/core.log #在整个系统中查找内存信息转储文件(core dump) ,
然后把结果保存到/tmp/core.log 文件中:
find . -type f -print | xargs grep "hostname" #用grep命令在所有的普通文件中搜索hostname这个词 find ./ -mtime +3 -print|xargs rm -f –r #删除3天以前的所有东西 (find . -ctime +3 -exec rm -rf {} \;) find ./ -size 0 | xargs rm -f & #删除文件大小为零的文件
basic 'find file' commands -------------------------- find / -name foo.txt -type f -print # full command find / -name foo.txt -type f # -print isn't necessary find / -name foo.txt # don't have to specify "type==file" find . -name foo.txt # search under the current dir find . -name "foo.*" # wildcard find . -name "*.txt" # wildcard find /users/al -name Cookbook -type d # search '/users/al' search multiple dirs -------------------- find /opt /usr /var -name foo.scala -type f # search multiple dirs case-insensitive searching -------------------------- find . -iname foo # find foo, Foo, FOo, FOO, etc. find . -iname foo -type d # same thing, but only dirs find . -iname foo -type f # same thing, but only files find files with different extensions ------------------------------------ find . -type f \( -name "*.c" -o -name "*.sh" \) # *.c and *.sh files find . -type f \( -name "*cache" -o -name "*xml" -o -name "*html" \) # three patterns find files that don't match a pattern (-not) -------------------------------------------- find . -type f -not -name "*.html" # find all files not ending in ".html" find files by text in the file (find + grep) -------------------------------------------- find . -type f -name "*.java" -exec grep -l StringBuffer {} \; # find StringBuffer in all *.java files find . -type f -name "*.java" -exec grep -il string {} \; # ignore case with -i option find . -type f -name "*.gz" -exec zgrep 'GET /foo' {} \; # search for a string in gzip'd files 5 lines before, 10 lines after grep matches ------------------------------------------- find . -type f -name "*.scala" -exec grep -B5 -A10 'null' {} \; (see http://alvinalexander.com/linux-unix/find-grep-print-lines-before-after-...) find files and act on them (find + exec) ---------------------------------------- find /usr/local -name "*.html" -type f -exec chmod 644 {} \; # change html files to mode 644 find htdocs cgi-bin -name "*.cgi" -type f -exec chmod 755 {} \; # change cgi files to mode 755 find . -name "*.pl" -exec ls -ld {} \; # run ls command on files found find and copy ------------- find . -type f -name "*.mp3" -exec cp {} /tmp/MusicFiles \; # cp *.mp3 files to /tmp/MusicFiles copy one file to many dirs -------------------------- find dir1 dir2 dir3 dir4 -type d -exec cp header.shtml {} \; # copy the file header.shtml to those dirs find and delete --------------- find . -type f -name "Foo*" -exec rm {} \; # remove all "Foo*" files under current dir find . -type d -name CVS -exec rm -r {} \; # remove all subdirectories named "CVS" under current dir find files by modification time ------------------------------- find . -mtime 1 # 24 hours find . -mtime -7 # last 7 days find . -mtime -7 -type f # just files find . -mtime -7 -type d # just dirs find files by modification time using a temp file ------------------------------------------------- touch 09301330 poop # 1) create a temp file with a specific timestamp find . -mnewer poop # 2) returns a list of new files rm poop # 3) rm the temp file find with time: this works on mac os x -------------------------------------- find / -newerct '1 minute ago' -print find and tar ------------ find . -type f -name "*.java" | xargs tar cvf myfile.tar find . -type f -name "*.java" | xargs tar rvf myfile.tar (see http://alvinalexander.com/blog/post/linux-unix/using-find-xargs-tar-crea... for more information) find, tar, and xargs -------------------- find . -name -type f '*.mp3' -mtime -180 -print0 | xargs -0 tar rvf music.tar (-print0 helps handle spaces in filenames) (see http://alvinalexander.com/mac-os-x/mac-backup-filename-directories-space...) locate command -------------- locate tomcat.sh # search the entire filesystem for 'tomcat.sh' (uses the locate database) locate -i spring.jar # case-insensitive search find and pax (instead of xargs and tar) --------------------------------------- find . -type f -name "*html" | xargs tar cvf jw-htmlfiles.tar - find . -type f -name "*html" | pax -w -f jw-htmlfiles.tar (see http://alvinalexander.com/blog/post/linux-unix/using-pax-instead-of-tar)
Xargs用法详解
【xargs定位参数位置 | xargs控制参数位置 | 如何定位控制xargs参数位置】
背景:管道+xargs用于把上游输出转换为下游参数输入。例如 ls *.bak | xargs rm -f
问题:xargs默认把输入作为参数放到命令的最后,但是很多命令需要自己定位参数的位置,比如拷贝命令cp {上游结果} destFolder
解决方法:xargs 使用大写字母i 定义参数指示符 -I <指示符>,然后用这个参数指示符定位参数插入的位置
例如:
ls *.bak | xargs -I % cp % /tmp/test
注释:这里使用%作为指示符,第一个%可以理解为声明,第二个%可以理解为调用。你也可以用其他字符,比如 ls *.bak | xargs -I {} cp {} /tmp/test
man xargs
-I replace-str
Replace occurrences of replace-str in the initial-arguments with
names read from standard input. Also, unquoted blanks do not
terminate input items; instead the separator is the newline
character. Implies -x and -L 1.
1. 简介
之所以能用到这个命令,关键是由于很多命令不支持|管道来传递参数,而日常工作中有有这个必要,所以就有了xargs命令,例如:
find /sbin -perm +700 |ls -l # 这个命令是错误的 find /sbin -perm +700 |xargs ls -l # 这样才是正确的
xargs 可以读入 stdin 的资料,并且以空白字元或断行字元作为分辨,将 stdin 的资料分隔成为 arguments 。 因为是 以空白字元作为分隔,所以,如果有一些档名或者是其他意义的名词内含有空白字元的时候, xargs 可能就会误判了~他的用法其实也还满简单的!就来看 一看先!
2. 选项解释
-0 当sdtin含有特殊字元时候,将其当成一般字符,想/'空格等
例如:
root@localhost:~/test#echo "//"|xargs echo
root@localhost:~/test#echo "//"|xargs -0 echo
/
-a file 从文件中读入作为sdtin,(看例一)
-e flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。(例二)
-p 当每次执行一个argument的时候询问一次用户。(例三)
-n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。(例四)
-t 表示先打印命令,然后再执行。(例五)
-i 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给{},可以用{}代替。(例六)
-r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。(例七)
-s num 命令行的最好字符数,指的是xargs后面那个命令的最大命令行字符数。(例八)
-L num Use at most max-lines nonblank input lines per command line.-s是含有空格的。
-l 同-L
-d delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符(例九)
-x exit的意思,主要是配合-s使用。
-P 修改最大的进程数,默认是1,为0时候为as many as it can ,这个例子我没有想到,应该平时都用不到的吧。
3. 应用举例
例一:
root@localhost:~/test#cat test #!/bin/sh echo "hello world/n" root@localhost:~/test#xargs -a test echo #!/bin/sh echo hello world/n root@localhost:~/test#
例二:
root@localhost:~/test#cat txt /bin tao shou kun root@localhost:~/test#cat txt|xargs -E 'shou' echo /bin tao root@localhost:~/test#
例三:
root@localhost:~/test#cat txt|xargs -p echo echo /bin tao shou kun ff ?...y /bin tao shou kun ff
例四:
root@localhost:~/test#cat txt|xargs -n1 echo /bin tao shou kun root@localhost:~/test3#cat txt|xargs echo /bin tao shou kun
例五:
root@localhost:~/test#cat txt|xargs -t echo echo /bin tao shou kun /bin tao shou kun
例六:
$ ls | xargs -t -i mv {} {}.bak
例七:
root@localhost:~/test#echo ""|xargs -t mv mv mv: missing file operand Try `mv --help' for more information. root@localhost:~/test#echo ""|xargs -t -r mv root@localhost:~/test# (直接退出)
例八:
root@localhost:~/test#cat test |xargs -i -x -s 14 echo "{}" exp1 exp5 file xargs: argument line too long linux-2 root@localhost:~/test# 例九: root@localhost:~/test#cat txt |xargs -i -p echo {} echo /bin tao shou kun ?...y root@localhost:~/test#cat txt |xargs -i -p -d " " echo {} echo /bin ?...y echo tao ?.../bin y echo shou ?...tao
再如:
root@localhost:~/test#cat test |xargs -i -p -d " " echo {} echo exp1 exp5 file linux-2 ngis_post tao test txt xen-3 ?...y root@localhost:~/test#cat test |xargs -i -p echo {} echo exp1 ?...y echo exp5 ?...exp1 y echo file ?...exp5 y
2、grep命令
grep (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。
2.1、grep命令的一般选项及实例
grep [OPTIONS] PATTERN [FILE...]
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]
grep命令用于搜索由Pattern参数指定的模式,并将每个匹配的行写入标准输出中。这些模式是具有限定的正则表达式,它们使用ed或 egrep命令样式。如果在File参数中指定了多个名称,grep命令将显示包含匹配行的文件的名称。对 shell 有特殊含义的字符 ($, *, [, |, ^, (, ), \ ) 出现在 Pattern参数中时必须带双引号。如果 Pattern参数不是简单字符串,通常必须用单引号将整个模式括起来。在诸如 [a-z], 之类的表达式中,-(减号)cml 可根据当前正在整理的序列来指定一个范围。整理序列可以定义等价的类以供在字符范围中使用。如果未指定任何文件,grep会假定为标准输入。
2.2、grep正则表达式元字符集(基本集)
^ 锚定行的开始 如:'^grep'匹配所有以grep开头的行。
$ 锚定行的结束 如:'grep$'匹配所有以grep结尾的行。
. 匹配一个非换行符的字符 如:'gr.p'匹配gr后接一个任意字符,然后是p。
* 匹配零个或多个先前字符 如:'*grep'匹配所有一个或多个空格后紧跟grep的行。 .*一起用代表任意字符。
[] 匹配一个指定范围内的字符,如'[Gg]rep'匹配Grep和grep。
[^] 匹配一个不在指定范围内的字符,如:'[^A-FH-Z]rep'匹配不包含A-R和T-Z的一个字母开头,紧跟rep的行。
.. 标记匹配字符,如:'love',love被标记为1。
\< 锚定单词的开始,如:'\<grep'匹配包含以grep开头的单词的行。
\> 锚定单词的结束,如'grep\>'匹配包含以grep结尾的单词的行。
x\{m\} 连续重复字符x,m次,如:'o\{5\}'匹配包含连续5个o的行。
x\{m,\} 连续重复字符x,至少m次,如:'o\{5,\}'匹配至少连续有5个o的行。
x\{m,n\} 连续重复字符x,至少m次,不多于n次,如:'o\{5,10\}'匹配连续5--10个o的行。
\w 匹配一个文字和数字字符,也就是[A-Za-z0-9],如:'G\w*p'匹配以G后跟零个或多个文字或数字字符,然后是p。
\W w的反置形式,匹配一个非单词字符,如点号句号等。\W*则可匹配多个。
\b 单词锁定符,如: '\bgrep\b'只匹配grep,即只能是grep这个单词,两边均为空格。
2.3、grep命令的常用选项及实例
-?
同时显示匹配行上下的?行,如:grep -2 pattern filename同时显示匹配行的上下2行。
-b,--byte-offset
打印匹配行前面打印该行所在的块号码。
-c,--count
只打印匹配的行数,不显示匹配的内容。
-f File,--file=File
从文件中提取模板。空文件中包含0个模板,所以什么都不匹配。
-h,--no-filename
当搜索多个文件时,不显示匹配文件名前缀。
-i,--ignore-case
忽略大小写差别。
-q,--quiet
取消显示,只返回退出状态。0则表示找到了匹配的行。
-l,--files-with-matches
打印匹配模板的文件清单。
-L,--files-without-match
打印不匹配模板的文件清单。
-n,--line-number
在匹配的行前面打印行号。
-s,--silent
不显示关于不存在或者无法读取文件的错误信息。
-v,--revert-match
反检索,只显示不匹配的行。
-w,--word-regexp
如果被\<和\>引用,就把表达式做为一个单词搜索。
-V,--version
显示软件版本信息。
=====
ls -l | grep '^a' 通过管道过滤ls -l输出的内容,只显示以a开头的行。
grep 'test' d* 显示所有以d开头的文件中包含test的行。
grep 'test' aa bb cc 显示在aa,bb,cc文件中匹配test的行。
grep '[a-z]' aa 显示所有包含每个字符串至少有5个连续小写字符的字符串的行。
grep 'w(es)t.*' aa 如果west被匹配,则es就被存储到内存中,并标记为1,然后搜索任意个字符(.*),这些字符后面紧跟着另外一个es(),找到就显示该行。如 果用egrep或grep -E,就不用""号进行转义,直接写成'w(es)t.*'就可以了。
grep -i pattern files :不区分大小写地搜索。默认情况区分大小写
grep -l pattern files :只列出匹配的文件名,
grep -L pattern files :列出不匹配的文件名,
grep -w pattern files :只匹配整个单词,而不是字符串的一部分(如匹配‘magic’,而不是‘magical’),
grep -C number pattern files :匹配的上下文分别显示[number]行,
grep pattern1 | pattern2 files :显示匹配 pattern1 或 pattern2 的行,
grep pattern1 files | grep pattern2 :显示既匹配 pattern1 又匹配 pattern2 的行。
一些常用的命令:
(1) find . -type f -exec ls -l {} \;
解释:查找当前路径下的所有普通文件,并把它们列出来。
(2)find logs -type f -mtime +5 -exec rm {} \;
解释:删除logs目录下更新时间为5日以上的文件。
(3)find . -name "*.log" -mtime +5 -ok rm {} \;
解释:删除当前路径下以。log结尾的五日以上的文件,删除之前要确认。
(4) find ~ -type f -perm 4755 -print
解释:查找$HOME目录下suid位被设置,文件属性为755的文件打印出来。
说明: find在有点系统中会一次性得到将匹配到的文件都传给exec,但是有的系统对exec的命令长度做限制,就会报:”参数列太长“,这就需要使用xargs。xargs是部分取传来的文件。
(5)find / -type f -print |xargs file
解释:xargs测试文件分类
(6)find . -name "core*" -print|xargs echo " ">/tmp/core.log
解释:将core文件信息查询结果报存到core。log日志。
(7)find / -type f -print | xargs chmod o -w
(8)find . -name * -print |xargs grep "DBO"
整理自以下网页:
http://hi.baidu.com/hehehehello/item/11ea49ca48a715d49644528d
http://www.360doc.com/content/12/0723/09/10467119_225923415.shtml
http://holy2010.blog.51cto.com/1086044/419871
http://blog.csdn.net/zhangfn2011/article/details/6776925
来源:http://www.bfcat.com/index.php/2012/07/find-xargs/