local shell=require("shell") local fs=require("filesystem") local text=require("text") local USAGE= [===[Usage: find [path] [--type=[dfs]] [--[i]name=EXPR] --path if not specified, path is assumed to be current working directory --type returns results of a given type, d:directory, f:file, and s:symlinks --name specify the file name pattern. Use quote to include *. iname is case insensitive --help display this help and exit]===] local args,options=shell.parse(...) if(not args or not options)or options.help then print(USAGE) if not options.help then return 1 else return end end if#args>1 then io.stderr:write(USAGE..'\n') return 1 end local path=#args==1 and args[1]or"." local bDirs=true local bFiles=true local bSyms=true local fileNamePattern="" local bCaseSensitive=true if options.iname and options.name then io.stderr:write("find cannot define both iname and name\n") return 1 end if options.type then bDirs=false bFiles=false bSyms=false if options.type=="f"then bFiles=true elseif options.type=="d"then bDirs=true elseif options.type=="s"then bSyms=true else io.stderr:write(string.format("find: Unknown argument to type: %s\n",options.type)) io.stderr:write(USAGE..'\n') return 1 end end if options.iname or options.name then bCaseSensitive=options.iname~=nil fileNamePattern=options.iname or options.name if type(fileNamePattern)~="string"then io.stderr:write('find: missing argument to `name\'\n') return 1 end if not bCaseSensitive then fileNamePattern=fileNamePattern:lower() end fileNamePattern=text.escapeMagic(fileNamePattern) fileNamePattern=fileNamePattern:gsub("%%%*",".*") end local function isValidType(spath) if not fs.exists(spath)then return false end if fileNamePattern:len()>0 then local fileName=spath:gsub('.*/','') if fileName:len()==0 then return false end local caseFileName=fileName if not bCaseSensitive then caseFileName=caseFileName:lower() end local s,e=caseFileName:find(fileNamePattern) if not s or not e then return false end if s~=1 or e~=caseFileName:len()then return false end end if fs.isDirectory(spath)then return bDirs elseif fs.isLink(spath)then return bSyms else return bFiles end end local function visit(rpath) local spath=shell.resolve(rpath) if isValidType(spath)then local result=rpath:gsub('/+$','') print(result) end if fs.isDirectory(spath)then local list_result=fs.list(spath) for list_item in list_result do visit(rpath:gsub('/+$','')..'/'..list_item) end end end visit(path)