注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Tsecer的回音岛

Tsecer的博客

 
 
 

日志

 
 

find 工具说明及其它  

2013-05-09 22:14:00|  分类: GNU工具链源码分 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
一、查找文件
查找文件的功能在windows下使用比较简单,经常是一个资料存放的位置不记得了,在大致范围内点击F3,或者系统级的搜索可以使用 win+F 来看是大范围内搜索。同样是在windows下,搜索到之后就是打开这个文件,执行只读(观看)或者修改操作,但是我想windows上大部分用户都是打开之后读取而不是修改该文件,键盘按不了几下。
如果在使用的linux系统中,很多时候都不是单单的一个文件的查找,而文件的命名通常也不会那么个性化,例如大量的日志和账单文件不可能每个都有一个拉轰的名字,搜索并不容易。另一方面,对于文件的搜索和提取需要经过各个不同的维度来过滤,例如几月几号几点到下一个几月几号几点的某种类型的文件中某个用户的某一条记录,这些信息可能分布在不同文件夹的不同文件。其实这些所有的输入条件就是一组不同的搜索条件,这个名字也是工具名find的由来,可能是互联网的搜索一般叫search,或者是find的拼写更加短小吧,总之文件的搜索工具名字就叫find。
二、工具的使用
工具的使用直接看find的手册即可,这里同样只是说明了工具的应用场景,而这些场景是只看代码所看不出来的,所以这里还是记录一下。对于find的实现思想,其实就是列举所有满足一定条件的文件的组合,而这个“条件的组合”始终是一个大的问题,它涉及到可能有哪些条件(比方说有没有搜索文件大小在那个范围内的功能),这些条件如何组合,这些都是基本的原始问题,也是一个工具设计时最为复杂的问题。
三、感兴趣的问题
其实我感兴趣的问题是其中执行的命令,所以看了一下find的源代码(没理解逻辑,只是看了软件包的文件布局),从代码包中可以看到,其中另外几个比较常用的工具 xargs、locate也在这个软件包里,软件包的名字叫做findutils文件包。其实从xargs和find中对于命令行的特殊替换方法{}就可以感觉到两者是有一定血缘关系的。
1、分号的转义
一个常见的疑问是为什么find里两个乍看起来非常诡异的使用方法,例如一个典型的使用方法
find ./ -mtime -1 -type f -ok ls -l {} \;
其中的 {} 替换为查找到的文件名,而最后的结束符需要进行转义,这两个是为什么呢?
对于分号的转义,这个大致想一下还是可以比较快的指导答案的,因为分号也是shell的关键字,单独的分号表示一条命令的结束,而find命令是被shell的语法解析命令首先解析,所以这个转义是给shell使用的,即让shell来放过这个特殊字符,而将这个字符原封不动的传递给find来使用。
这里再次引入一个问题,既然对于find来说,分号表示是一条命令的结束,那么如果要在find中执行多条命令该如何表示呢?
2、大括号对表示占位符
这个和我们之前见到的替换规则都不相同,这里使用两个字符来表示替换内容,而shell中绝大部分时间是通过单个字符表示,例如星号表示零个或者多个字符,这里使用两个字符并且是空的字符的格式让人比较费解,为什么不使用其它的单词或则字符来组合成一个替换占位符呢?
四、问题的讨论
无意中搜索到关于这个表达方式的讨论关于括号对 说明,大致的意思是说,其它的单词都被shell占用完了,正所谓“世间好语书说尽,天下名山僧占多”就是这个意思。为了避免每次调用find的时候在每个占位符的地方都都加上像分号一样的转义,find使用了这个相对低调的括号对,链接中说明了shell对于 圆括号(作为命令、算数表达式等)、 中括号(文件名展开)等都已经被使用,其它的单个的字符更是被shell使用殆尽,所以find使用了这个组合。
不过 大括号也不是天真无邪的,它在shell中出现的频率也不低,例如作为一个指令组的定界符,或者是作为一个展开变量的定界符,例如file${var}suff形式的展开。
和其他的两个括号相比,大括号的优点在于它不是shell的元字符(即meta char),所谓元字符就是说这个字符如果没有被引注(quoted),那么它即使和其他字符放在一起,依然可以被识别并作为定界功能,这个定界的功能就是空白(空格、制表符)的基本作用。
1、bash中对于元字符的处理
syntax.h
#define shell_meta_chars   "()<>;&|"
#define shell_break_chars  "()<>;&| \t\n"
#define shell_glob_chars "*?[]^"
这个syntax和bash的词法、语法分析紧密结合,结合的意思就是说:它是词法分析和语法分析阶段就需要进行特殊处理的,而其他的可能是在语义处理的阶段才进行展开,由于词法和语法分析早于语义分析,所以这里的优先级就会更高。
事实上看一下bash的语法分析可以看到,在词法分析阶段shell同样是做了大量特殊处理,例如对于美元符号的特殊处理,但是无论如何,在这里没有看到对于美元符号和大括号的使用。
2、shell对于大括号的使用和处理
在前面的链接中,说明了大括号只有在特定的条件下才具有保留字的意义,没有被引用、必须是命令的第一个单词。虽然对于连续的大括号可以表示集合的替换,但是对于没有夹在单词前后,或者中间没有特殊的逗号或者亮点分割的都不会被识别和展开。而bash中对于这些语法的处理文件为
expand_word_list_internal
  if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
    new_list = brace_expand_word_list (new_list, eflags);
brace_expand (text)--->>.expand_seqterm
  /* If the amble does not contain an unquoted BRACE_ARG_SEPARATOR, then
     just return without doing any expansion.  */
  j = 0;
  while (amble[j])
    {
      if (amble[j] == '\\')
{
 j++;
 ADVANCE_CHAR (amble, alen, j);
 continue;
}

      if (amble[j] == brace_arg_separator)
break;

      ADVANCE_CHAR (amble, alen, j);
    }

  if (amble[j] == 0)
    {//执行到这里,说明大括号内没有包含逗号,此时在其中搜索两个连续的逗号,表示一个范围,如果没有则返回错误
      tack = expand_seqterm (amble, alen);
      if (tack)
goto add_tack;
      else
{
 free (amble);
 free (preamble);
 result[0] = savestring (text);
 return (result);
}
    }
由于大括号对中没有包含逗号即连点符,所以这个空的括号对被按照字面量返回,注意的是两个字符必须连续,就好象for的三个字符必须连续一样。
五、如何对于执行多条命令
find ./ -flags noopaque -exec cmd1 -exec cmd2

另外一个直观的方案
[root@Harry emptyarr]# find . -name "*" -exec 'ls {}' \;
find: `ls .': No such file or directory
find: `ls ./emptyarr.c': No such file or directory
find: `ls ./a.out': No such file or directory
使用strace显示执行命令
[pid  5894] fchdir(3)                   = 0
[pid  5894] execve("ls ./a.out", ["ls ./a.out"], [/* 47 vars */]) = -1 ENOENT (No such file or directory)

这其实是shell传递给进程的单词分段方式不同而已,例如

test "some spaces"  over
则main函数中看到argc 为2,其中argv[1] = "some space"
当这个整体被作为一个命令的开始也就是可执行文件的路径时,问题就出现了。
  评论这张
 
阅读(558)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017