IonutParau 687cfebd00 testing version of LuaBIOS and OpenOS
people were having issues getting them to work so now we promote consistency
2025-06-28 20:41:49 +02:00

133 lines
2.8 KiB
Lua

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 -- nil return, meaning no error
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
-- prefix any * with . for gnu find glob matching
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)