#!/bin/sh cat << 'EEE' > /dev/null /* fnf .... find file, find parser * Copyright (C) 2017-2019 Momi-g * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ EEE # cmd='-h bool 0 # -r int -1 # -o bool 0' # buf=`prsopt "$cmd"` # eval "$buf" # if [ $? -ne 0 ] ; then echo "$0: optErr. $OPTARG" >/dev/stderr ; exit 1; fi # func_rdopt() { ( rdopt_fmt="$1" # ":ab:c" etc. format. shift #ck quiet mode rdopt_quiet=1 rdopt_buf=${rdopt_fmt%%[!:]*} if [ "$rdopt_buf" != ':' ] ; then rdopt_quiet=0 rdopt_fmt=':'"$rdopt_fmt" fi #--inicialize make list opt_a='', ... #ab:c -> 'a' \n 'b' \n 'c' \n rdopt_buf='s/://g s/./&\ /g' rdopt_zerolist=`echo "$rdopt_fmt" | sed -e "$rdopt_buf" | sed -e " /^$/d s/^/opt_/g s/$/=''/g " ` #--- local vars # rdopt_fmt="$1" # ":ab:c" opt format # rdopt_quiet=1 # rdopt_zerolist=`echo "$rdopt_fmt" | sed -e "$rdopt_buf" | sed -e " # rdopt_buf='s/://g rdopt_out="" rdopt_opt="" rdopt_skip="" rdopt_err="" rdopt_safe=" s#'#'\"'\"'#g 1 s/^/'/g $ s/$/'/g" #---getopts loop. break if all args read or detect '--' while : do if [ 0 -eq "$#" ] || [ "$rdopt_err" = "1" ] ; then break fi if [ "$1" = "--" ] ; then shift ; break fi getopts "$rdopt_fmt" rdopt_opt "$@" # ":a:bc:f:" etc... # err detect@silent mode # $?=1 ... detect optend or '--'. '--' is removed at previous line. # ':' ... detect option, but dont have subargs (OPTARG="factor"). # '?' ... detect unsupported option char (OPTARG="factor") or args end (OPTARG="blank"). # OPTARG ... "" is optend. "a/b/c..." is invalid option # OPTIND ... if err, OPTIND indicates next (new) arg pos. if [ "$?" = "1" ] ; then # normal end (detect normal args). save general args. shift $((OPTIND - 1)) if [ "$#" -eq "0" ] ; then break fi # new set make rdopt_buf=`printf '%s' "$1" | sed -e "$rdopt_safe"` rdopt_skip="$rdopt_skip $rdopt_buf" shift OPTIND=1 continue fi if [ "$rdopt_opt" = "?" ] || [ "$rdopt_opt" = ":" ] ; then # detect invalid opt rdopt_err=1 #OPTARG has err option char. continue fi # normal. detect option. if [ "$OPTARG" = "" ] ; then # no subargs rdopt_out="$rdopt_out opt_$rdopt_opt"'=1' else # exist subargs rdopt_buf=`printf "%s\n" "$OPTARG" | sed -e "$rdopt_safe" ` rdopt_out="$rdopt_out opt_$rdopt_opt"'='"$rdopt_buf" fi done # exit parse if [ "$rdopt_err" = "1" ] ; then if [ "$rdopt_quiet" = "0" ] ; then rdopt_buf=${0##*/} echo "$rdopt_buf: invalid option. sleep. ( $OPTARG )" >/dev/stderr while : do sleep 1000 done else rdopt_out="OPTARG=$OPTARG OPTIND=1 test 1 = 0" fi else # '--' end if [ "$#" != "0" ] ; then rdopt_buf=`cat << 'EEE' for ii do printf '%s' "$ii" | sed -e " s#'#'\"'\"'#g 1 s/^/'/g $ s/$/' /g" done EEE ` rdopt_buf=`eval "$rdopt_buf"` rdopt_skip="$rdopt_skip $rdopt_buf" fi rdopt_out="OPTIND=1 $rdopt_zerolist $rdopt_out set -- $rdopt_skip " fi printf '%s\n' "$rdopt_out" # clean OPTIND=1 rdopt_fmt="" rdopt_quiet="" rdopt_zerolist="" rdopt_buf="" rdopt_out="" rdopt_opt="" rdopt_skip="" rdopt_err="" rdopt_safe="" ) OPTIND=1 } buf=`func_rdopt "hr:oP" "$@"` eval "$buf" if [ $? -ne 0 ] ; then echo "$0: optErr. $OPTARG" >/dev/stderr ; exit 1; fi if [ "$opt_h" = '1' ] ; then cat << 'EEE' HowTo (find file/directry) option: -h(elp), -r(ecurse -1(dfl),0,1,2..), -o(ctal output) ------ ex.) ~$ fnf txt unko (-r -1) #search files from ./ >>> ./unko___uh.txt ./unko.txt ./unkotxt/ ...show include 'txt' + 'unko' (fixed)string in filepath (not file name) ...recursive search (-1:non stop 0:pwd 1:pwd+next) ...directry(or directry link) is end with '/'. ex.) ~$ fnf '/u' unko //uh >>> ./unko.txt >>> '//' means 'not'. '/u' && 'unko' && !'uh' ... normal filepath probably should not contain '//'. (./aaa//bbb/c.txt etc) ex.) ~$ fnf txt unko -o >>> \001\004\123... >>> printf '\001\004\123...' -> ./unko___uh.txt \111\333... ... output in octal number. You can safely handle filenames containing newlines and unicode characters. ("./aaa/bb\n\n\123 b/ccc.txt" etc) EEE exit 0 fi # -P縺ョ繝�ヵ繧ゥ縺ァ譎ョ騾壹↓max縺、縺代※讀懃エ「縲Uype l縺ァ繧キ繝ウ繝懊Μ繝�け繝ェ繝ウ繧ッ繧呈爾縺怜�縺励※鬆ュ縺ォ//0縺ソ縺溘>縺ェ # 繝輔Λ繧ー繧偵▽縺代※蜀肴、懃エ「縺輔○繧九→縺九Naxdepth縺御スソ縺医�繝シ縲ょセョ螯吶□縲らャャ荳髫主ア、縲∫ャャ莠碁嚴螻、縺」縺ヲ諢溘§縺ォ # 讀懃エ「縺輔○縺ヲ繧ケ繝ゥ繝�す繝・繧ォ繧ヲ繝ウ繝�purne縺ァ縺カ縺」縺。縺弱k縺ィ縺九Moop蟇セ遲悶′縺ゥ繝シ繧茨シ� # find縺ッ繝代ち繝シ繝ウ縺後す繧ァ繝ォ繝代ち繝シ繝ウ縺ェ縺ョ縺ァ縲√◎縺ョ縺ク繧薙b縲�-path縺ァ繝代せ蛛・菴懊↓縺ェ繧� # find . -path ./src/emacs -prune -o -print # find縺ッ遒コ蝗コ,-o -a縺ィ蜷ヲ螳壹�縺ソ隕冗ィ九� # find . -path '*/*/*' -prune find -print0 --version >/dev/null 2>&1 if [ "$?" = "0" ] && [ "$opt_P" != "1" ]; then echo "// (stderr info) detect gnu-find. use fastmode." >/dev/stderr gnumode=1 fi if [ "$opt_r" != "-1" ] && [ "$opt_r" != "" ] ; then ptn='*/*/*' #>> pwd縺ッ/荳縺、縺�縺代�//縺ッ繧オ繝悶ョ繧」繝ャ繧ッ繝医Μ縲�///縺ッ繧オ繝悶し繝悶� for ii in `seq 1 $opt_r ` do ptn="$ptn"'/*' done else ptn='*//*' # 蝓コ譛ャ逧�↓//繧貞性繧繝輔ぃ繧、繝ォ縺ッ蟄伜惠縺怜セ励↑縺�ゅヵ繧。繧、繝ォ蜷阪↓\000縺ィ/縺ッ菴ソ縺医↑縺�◆繧√� # null_hit縺ァ譫晏�繧翫r髦イ縺舌� fi # maxdepth縺掲ind縺ァ菴ソ縺医↑縺��縺ァ莉」譖ソ縲Qosix. outstr='cat -' if [ "$opt_o" != "1" ] ; then outstr='while read -r aa do printf "$aa" echo done' fi # syscall繧ェ繝シ繝舌�繝倥ャ繝峨′驥阪>縺代←縲∥wk縺ィ縺菊val菴ソ縺医↑縺�@縲�%b繧ゅす繧ァ繝ォ縺�縺代□縺励� # printf閾ェ菴薙�built-in縺�縺九i縲∬�蜻ス逧�↓驕�> # 縺」縺ヲ縺サ縺ゥ縺倥c縺ェ縺�Bwk縺ォ豈斐∋縺溘i500%繝励Λ繧ケ縺」縺ヲ縺ィ縺薙� awk 10ms -> while print 50ms # 20ms # 蝗コ螳壽枚蟄玲、懃エ「縺ョ縺ソ縺ォ邨槭k縲よ、懃エ「譁�ュ励b逕溘□縺ィ謇ア縺�↓縺上>縺ョ縺ァ8騾イ縺ォ縺励→縺上� buf=`for ii in "$@" do printf '%s\000' "$ii" done | od -An -to1 -w16 -v | tr -d '\n' | sed -e 's# 000#@#g' | tr ' ' 'o' | tr '@' '\n' ` filter="" for ii in $buf do buf=${ii#o057o057} # //bbb 縺ソ縺溘>縺ェ'//'莉倥″譁�ュ怜�縺ッ蜷ヲ螳壹Oot. if [ "$buf" != "$ii" ] ; then filter="$filter /$buf/ d" else filter="$filter /$buf/ ! d" fi done filter="sed -e '$filter'" # echo "$filter" # exit # sed -e ' # /o141o141/ ! d # /o163o163/ ! d # /o144o144/ d' # sed -e '' # ---main # -L縺ッtype縺ァ繝輔か繝ォ繝邉サ縺ョ陦ィ遉コ縺ョ蟆サ蟆セ縺ォ/繧貞愛蛻・縺吶k縺ィ縺阪‥ir繝ェ繝ウ繧ッ譎ゅ↓諠��ア縺梧ャイ縺励>縺ョ縺ァ縲� # . 縺ィ./縺ァ豺キ蝨ィ縺励※繧九ょ、峨Ms縺ッ--indi縺ァ/謖�ョ壹〒縺阪k縺代←縲’ind縺ォ縺ッ縺ェ縺�� # -L ./ 縺ィ -L .縺ァ驕輔≧縲ゅヰ繧ー縺」縺ヲ縺サ縺ゥ縺倥c縺ェ縺�¢縺ゥ豕ィ諢上′蠢�ヲ√� # echo "$ptn" # exit # -exec縺碁≦縺�∩縺溘>縲�20ms -> 800ms # 20ms time find -L ./ -path "@@" -prune -o -print # 700ms time find -L ./ -path "@@" -prune -o -exec printf '%s\n' '{}' ';' # syscall縺碁≦縺�°繧�//繧剃スソ縺」縺ヲ菴輔→縺九〒縺阪s縺九�...辟。逅�ょ�蜉帙☆繧区婿豕輔′縺ェ縺�� # exec縺ァ縺セ縺ィ繧√i繧後※縺励∪縺」縺ヲ繧九Hnu縺ィ繧ケ繧、繝�メ縺九↑縲� # gnu can use -printf ... fast output(40ms) if [ "$gnumode" = "1" ] ; then cmd=`cat << 'EEE' find -L ./ -path "$ptn" -prune \ -o -type d -a '!' -path '*/' -a -printf '%p/\000' \ -o -printf '%p\000' EEE ` else # posix & syscall. slow. 800ms cmd=`cat << 'EEE' find -L ./ -path "$ptn" -prune \ -o -type d -a '!' -path '*/' -a -exec printf '%s/\000' '{}' ';' \ -o -exec printf '%s\000' '{}' ';' EEE ` fi eval "$cmd" | od -An -to1 -w16 -v | sed -e 's# 000#@#g' | tr -d '\n' | tr ' ' 'o' | tr '@' '\n' | eval "$filter" | tr 'o' '\134' | eval "$outstr" # . 繝代せ縺九i謗「縺怜�縺励◆荳縺、荳縺、縺ョ繝輔ぃ繧、繝ォ縺ォ螟ァ縺励※ # pathname縺継tn縺ォ荳閾エ縺励◆繧画升繧翫▽縺カ縺吶ゅ◎縺ョ蜈医�繝輔か繝ォ繝繧りヲ九↑縺九▲縺溘%縺ィ縺ォ縺輔l繧九�(prune) # -o or. 謠。繧翫▽縺カ縺輔l縺ェ縺九▲縺溽函縺肴ョ九j縺ォ蟇セ縺励※ # -o type d 蟇セ雎。繝輔ぃ繧、繝ォ蜷阪′繝�ぅ繝ャ繧ッ繝医Μ縺九▽(-a) path蜷阪′/縺ァ邨ゅo縺」縺ヲ縺ェ縺�(!...蜷ヲ螳�) # 縺ョ縺ェ繧峨�縲+}/\000繧貞�蜉帙りソ斐j蛟、縺ッ縺薙%縺ァtrue縺ェ縺ョ縺ァ蠕後m縺ョ隧穂セ。縺ッ繧ケ繧ュ繝��縺輔l繧九� # -o 荳翫′螟ア謨励√▽縺セ繧翫ョ繧」繝ャ繧ッ繝医Μ縺ィ縺九§繧�↑縺��縺ェ繧峨�{}\000繧貞�蜉帙� # -o縺ッelse縺ォ霑代>縲� # # 遲我セ。繧ウ繝シ繝� # loop: # # mode=read_linkend_data(); (-L) # obj=search(dir); # # if (pathname == $ptn ){ ptn縺ッ繧キ繧ァ繝ォ繝代ち繝シ繝ウ. */縺ィ縺�??123*/縺ィ縺九� # next # } else if (obj==dir && pathname != '*/') { # printf obj + '/' + '\000' # next # } else { # printf obj + '\000' # next # } # loopend #