#!/bin/sh # find a string in the current directory and below # while automatically ignoring repository metadata. # Licence: LGPLv2 # Author: # http://www.pixelbeat.org/ # Notes: # One can either supply a regular expression or fixed string. # If just a fixed string is supplied then we specify the -F option to # grep so that it uses fast string matching (why doesn't it do this itself?), # otherwise we default to an extended regular expression. # The match type auto selection is disabled if a specific grep # match type is specified as part of the optional grep options. # Changes: # V0.1, 25 Apr 2005, Initial release # V0.2, 25 Mar 2008, Add grep colours if available # Add more repo dirs to ignore # Support regular expressions not just fixed strings # Support passing extra user specified options to grep # V0.3, 26 Mar 2008, Fix bug generating $repo_ign dirs # V0.4, 30 Sep 2008, Tweak grep colour to be usable on light terminals # V0.7, 29 Jan 2015 # http://github.com/pixelb/scripts/commits/master/scripts/findrepo proc usage { shell { echo "Usage: $[basename $0] ['grep options'] search_expr [file wildcard] examples: $[basename $0] 'main' '*.[ch]' #fixed string search $[basename $0] '(main|mane)' '*.[ch]' #regular expression search $[basename $0] '-F' 'main(' '*.[ch]' #force fixed string search $[basename $0] '-L -F' 'main(' '*.[ch]' #extra grep options" } >&2 exit 1 } if test $Argc -eq 0 || test $Argc -gt 3 { usage } #enable search highlighting if supported by grep echo | grep --color=auto "" >/dev/null !2 > !1 && global colour := '"--color=auto'" if test $Argc -eq 1 { global glob := ''*'' # common shortcut to avoid needing to specify all files } elif test $Argc -eq 2 { # if $1 begins with a '-' then we might be hitting the # ambiguous case where grep options are being specified, # so warn with info about (avoiding) the ambiguity if ! test $(1##-*) { echo "\ Warning: treating '$1' as the grep pattern, not extra options. If this is intended, avoid the warning with an empty first parameter. If this is not intended, please specify the file wildcard." > !2 } global glob := $2 } elif test $Argc -eq 3 { global grep_options := $1 shift global glob := $2 } #default to -E or -F as appropriate, not -G if ! printf "%s\n" $grep_options | grep -E -- "-([EFGP]|regexp|fixed)" >/dev/null !2 > !1 { #used fixed string matching for speed unless an ERE metacharacter used echo $1 | grep '[.[\()*+?{|^$]' >/dev/null && global type := '"-E'" || global type := '"-F'" global grep_options := ""$grep_options $type"" } global repodirs := '".git .svn CVS .hg .bzr _darcs'" for dir in [$repodirs] { global repo_ign := ""$repo_ign$(repo_ign+" -o ")-name $dir"" } find . '(' -type d -a '(' $repo_ign ')' ')' -prune -o \ '(' -type f -name $glob -print0 ')' | #LANG=C is to work around grep multibyte inefficiencies #GREP_COLOR="1;37;47" is bright yellow on black bg env GREP_COLOR="1;33;40" LANG=C xargs -0 grep $colour $grep_options -- $1 (CommandList children: [ (FuncDef name: usage body: (BraceGroup children: [ (Subshell child: (C {(echo)} { (DQ ("Usage: ") (CommandSubPart command_list: (CommandList children: [(C {(basename)} {($ VSub_Number "$0")})] ) left_token: spids: [84 88] ) (" ['grep options'] search_expr [file wildcard]\n") ("examples: ") (CommandSubPart command_list: (CommandList children: [(C {(basename)} {($ VSub_Number "$0")})] ) left_token: spids: [91 95] ) (" 'main' '*.[ch]' #fixed string search\n") (" ") (CommandSubPart command_list: (CommandList children: [(C {(basename)} {($ VSub_Number "$0")})] ) left_token: spids: [98 102] ) (" '(main|mane)' '*.[ch]' #regular expression search\n") (" ") (CommandSubPart command_list: (CommandList children: [(C {(basename)} {($ VSub_Number "$0")})] ) left_token: spids: [105 109] ) (" '-F' 'main(' '*.[ch]' #force fixed string search\n") (" ") (CommandSubPart command_list: (CommandList children: [(C {(basename)} {($ VSub_Number "$0")})] ) left_token: spids: [112 116] ) (" '-L -F' 'main(' '*.[ch]' #extra grep options") ) } ) redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[122])] spids: [78 120] ) (C {(exit)} {(1)}) ] spids: [76] ) spids: [72 75] ) (If arms: [ (if_arm cond: [ (Sentence child: (AndOr children: [ (C {(Lit_Other "[")} {($ VSub_Pound "$#")} {(-eq)} {(0)} {(Lit_Other "]")}) (C {(Lit_Other "[")} {($ VSub_Pound "$#")} {(-gt)} {(3)} {(Lit_Other "]")}) ] op_id: Op_DPipe ) terminator: ) ] action: [(C {(usage)})] spids: [-1 158] ) ] spids: [-1 163] ) (AndOr children: [ (Pipeline children: [ (C {(echo)}) (SimpleCommand words: [{(grep)} {(--color) (Lit_Other "=") (auto)} {(DQ )}] redirects: [ (Redir op_id:Redir_Great fd:-1 arg_word:{(/dev/null)} spids:[182]) (Redir op_id:Redir_GreatAnd fd:2 arg_word:{(1)} spids:[185]) ] ) ] negated: False ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:colour) op: Equal rhs: {(DQ ("--color=auto"))} spids: [190] ) ] spids: [190] ) ] op_id: Op_DAmp ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {($ VSub_Pound "$#")} {(-eq)} {(1)} {(Lit_Other "]")}) terminator: ) ] action: [ (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:glob) op:Equal rhs:{(SQ <"*">)} spids:[212])] spids: [212] ) ] spids: [-1 209] ) (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {($ VSub_Pound "$#")} {(-eq)} {(2)} {(Lit_Other "]")}) terminator: ) ] action: [ (If arms: [ (if_arm cond: [ (Sentence child: (Pipeline children: [ (C {(test)} { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_DPound arg_word:{("-*")}) spids: [255 259] ) ) } ) ] negated: True ) terminator: ) ] action: [ (SimpleCommand words: [ {(echo)} { (DQ ("Warning: treating '") ($ VSub_Number "$1") ("' as the grep pattern, not extra options.\n") ("If this is intended, avoid the warning with an empty first parameter.\n") ("If this is not intended, please specify the file wildcard.") ) } ] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[277])] ) ] spids: [-1 263] ) ] spids: [-1 281] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:glob) op: Equal rhs: {(DQ ($ VSub_Number "$2"))} spids: [284] ) ] spids: [284] ) ] spids: [220 233] ) (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {($ VSub_Pound "$#")} {(-eq)} {(3)} {(Lit_Other "]")}) terminator: ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:grep_options) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [305] ) ] spids: [305] ) (C {(shift)}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:glob) op: Equal rhs: {(DQ ($ VSub_Number "$2"))} spids: [314] ) ] spids: [314] ) ] spids: [289 302] ) ] spids: [-1 319] ) (If arms: [ (if_arm cond: [ (Sentence child: (Pipeline children: [ (C {(printf)} {(DQ ("%s") (EscapedLiteralPart token:))} {(DQ ($ VSub_Name "$grep_options"))} ) (SimpleCommand words: [{(grep)} {(-E)} {(--)} {(DQ ("-([EFGP]|regexp|fixed)"))}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(/dev/null)} spids: [353] ) (Redir op_id: Redir_GreatAnd fd: 2 arg_word: {(1)} spids: [356] ) ] ) ] negated: True ) terminator: ) ] action: [ (AndOr children: [ (Pipeline children: [ (C {(echo)} {(DQ ($ VSub_Number "$1"))}) (SimpleCommand words: [{(grep)} {(SQ <"[.[\\()*+?{|^$]">)}] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(/dev/null)} spids:[381])] ) ] negated: False ) (AndOr children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:type) op: Equal rhs: {(DQ (-E))} spids: [386] ) ] spids: [386] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:type) op: Equal rhs: {(DQ (-F))} spids: [393] ) ] spids: [393] ) ] op_id: Op_DPipe ) ] op_id: Op_DAmp ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:grep_options) op: Equal rhs: {(DQ ($ VSub_Name "$grep_options") (" ") ($ VSub_Name "$type"))} spids: [399] ) ] spids: [399] ) ] spids: [-1 360] ) ] spids: [-1 406] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:repodirs) op: Equal rhs: {(DQ (".git .svn CVS .hg .bzr _darcs"))} spids: [409] ) ] spids: [409] ) (ForEach iter_name: dir iter_words: [{($ VSub_Name "$repodirs")}] do_arg_iter: False body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:repo_ign) op: Equal rhs: { (DQ ($ VSub_Name "$repo_ign") (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_Plus arg_word:{(DQ (" -o "))}) spids: [429 435] ) ("-name ") ($ VSub_Name "$dir") ) } spids: [426] ) ] spids: [426] ) ] spids: [423 440] ) spids: [419 421] ) (Pipeline children: [ (C {(find)} {(.)} {(EscapedLiteralPart token:)} {(-type)} {(d)} {(-a)} {(EscapedLiteralPart token:)} {($ VSub_Name "$repo_ign")} {(EscapedLiteralPart token:)} {(EscapedLiteralPart token:)} {(-prune)} {(-o)} {(EscapedLiteralPart token:)} {(-type)} {(f)} {(-name)} {(DQ ($ VSub_Name "$glob"))} {(-print0)} {(EscapedLiteralPart token:)} ) (SimpleCommand words: [ {(xargs)} {(-0)} {(grep)} {($ VSub_Name "$colour")} {($ VSub_Name "$grep_options")} {(--)} {(DQ ($ VSub_Number "$1"))} ] more_env: [ (env_pair name:GREP_COLOR val:{(DQ ("1;33;40"))} spids:[493]) (env_pair name:LANG val:{(C)} spids:[498]) ] ) ] negated: False ) ] )