shell tools: globbing
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
{
|
||||
title = 'Shell utilities',
|
||||
repository = 'kepler155c/opus-apps/{{OPUS_BRANCH}}/openos',
|
||||
description = [[Experimental!
|
||||
Utilties for shell: grep, cat, touch, etc ]],
|
||||
licence = 'MIT',
|
||||
}
|
||||
331
openos/tree.lua
331
openos/tree.lua
@@ -1,331 +0,0 @@
|
||||
local computer = require("openos.computer")
|
||||
local shell = require("openos.shell")
|
||||
local fs = require("openos.filesystem")
|
||||
local tx = require("openos.transforms")
|
||||
local text = require("openos.text")
|
||||
|
||||
local args, opts = shell.parse(...)
|
||||
|
||||
local function die(...)
|
||||
io.stderr:write(...)
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
do -- handle cli
|
||||
if opts.help then
|
||||
print([[Usage: tree [OPTION]... [FILE]...
|
||||
-a, --all do not ignore entries starting with .
|
||||
--full-time with -l, print time in full iso format
|
||||
-h, --human-readable with -l, print human readable sizes
|
||||
--si likewise, but use powers of 1000 not 1024
|
||||
--level=LEVEL descend only LEVEL directories deep
|
||||
--color=WHEN WHEN can be
|
||||
auto - colorize output only if writing to a tty,
|
||||
always - always colorize output,
|
||||
never - never colorize output; (default: auto)
|
||||
-l use a long listing format
|
||||
-f print the full path prefix for each file
|
||||
-i do not print indentation lines
|
||||
-p append "/" indicator to directories
|
||||
-Q, --quote quote filenames with double quotes
|
||||
-r, --reverse reverse order while sorting
|
||||
-S sort by file size
|
||||
-t sort by modification type, newest first
|
||||
-X sort alphabetically by entry extension
|
||||
-C do not count files and directories
|
||||
-R count root directories like other files
|
||||
--help print this help and exit]])
|
||||
return 0
|
||||
end
|
||||
|
||||
if #args == 0 then
|
||||
table.insert(args, ".")
|
||||
end
|
||||
|
||||
opts.level = tonumber(opts.level) or math.huge
|
||||
if opts.level < 1 then
|
||||
die("Invalid level, must be greater than 0")
|
||||
end
|
||||
|
||||
opts.color = opts.color or "auto"
|
||||
if opts.color == "auto" then
|
||||
opts.color = io.stdout.tty and "always" or "never"
|
||||
end
|
||||
|
||||
if opts.color ~= "always" and opts.color ~= "never" then
|
||||
die("Invalid value for --color=WHEN option; WHEN should be auto, always or never")
|
||||
end
|
||||
end
|
||||
|
||||
local lastYield = computer.uptime()
|
||||
local function yieldopt()
|
||||
if computer.uptime() - lastYield > 2 then
|
||||
lastYield = computer.uptime()
|
||||
os.sleep(0)
|
||||
end
|
||||
end
|
||||
|
||||
local function peekable(iterator, state, var1)
|
||||
local nextItem = {iterator(state, var1)}
|
||||
|
||||
return setmetatable({
|
||||
peek = function()
|
||||
return table.unpack(nextItem)
|
||||
end
|
||||
}, {
|
||||
__call = coroutine.wrap(function()
|
||||
while true do
|
||||
local item = nextItem
|
||||
nextItem = {iterator(state, nextItem[1])}
|
||||
coroutine.yield(table.unpack(item))
|
||||
if nextItem[1] == nil then break end
|
||||
end
|
||||
end)
|
||||
})
|
||||
end
|
||||
|
||||
local function filter(entry)
|
||||
return opts.a or entry:sub(1, 1) ~= "."
|
||||
end
|
||||
|
||||
local function stat(path)
|
||||
local st = {}
|
||||
st.path = path
|
||||
st.name = fs.name(path) or "/"
|
||||
st.sortName = st.name:gsub("^%.","")
|
||||
st.time = fs.lastModified(path)
|
||||
st.isLink = fs.isLink(path)
|
||||
st.isDirectory = fs.isDirectory(path)
|
||||
st.size = st.isLink and 0 or fs.size(path)
|
||||
st.extension = st.name:match("(%.[^.]+)$") or ""
|
||||
st.fs = fs.get(path)
|
||||
return st
|
||||
end
|
||||
|
||||
local colorize
|
||||
if opts.color == "always" then
|
||||
-- from /lib/core/full_ls.lua
|
||||
local colors = tx.foreach(text.split(os.getenv("LS_COLORS") or "", {":"}, true), function(e)
|
||||
local parts = text.split(e, {"="}, true)
|
||||
return parts[2], parts[1]
|
||||
end)
|
||||
|
||||
function colorize(stat)
|
||||
return stat.isLink and colors.ln or
|
||||
stat.isDirectory and colors.di or
|
||||
colors["*" .. stat.extension] or
|
||||
colors.fi
|
||||
end
|
||||
end
|
||||
|
||||
local function list(path)
|
||||
return coroutine.wrap(function()
|
||||
local l = {}
|
||||
for entry in fs.list(path) do
|
||||
if filter(entry) then
|
||||
table.insert(l, stat(fs.concat(path, entry)))
|
||||
end
|
||||
end
|
||||
|
||||
if opts.S then
|
||||
table.sort(l, function(a, b)
|
||||
return a.size < b.size
|
||||
end)
|
||||
elseif opts.t then
|
||||
table.sort(l, function(a, b)
|
||||
return a.time < b.time
|
||||
end)
|
||||
elseif opts.X then
|
||||
table.sort(l, function(a, b)
|
||||
return a.extension < b.extension
|
||||
end)
|
||||
else
|
||||
table.sort(l, function(a, b)
|
||||
return a.sortName < b.sortName
|
||||
end)
|
||||
end
|
||||
|
||||
for i = opts.r and #l or 1, opts.r and 1 or #l, opts.r and -1 or 1 do
|
||||
coroutine.yield(l[i])
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local function digRoot(rootPath)
|
||||
coroutine.yield(stat(rootPath), {})
|
||||
|
||||
if not fs.isDirectory(rootPath) then
|
||||
return
|
||||
end
|
||||
local iterStack = {peekable(list(rootPath))}
|
||||
local pathStack = {rootPath}
|
||||
local levelStack = {not not iterStack[#iterStack]:peek()}
|
||||
|
||||
|
||||
repeat
|
||||
local entry = iterStack[#iterStack]()
|
||||
|
||||
if entry then
|
||||
levelStack[#levelStack] = not not iterStack[#iterStack]:peek()
|
||||
|
||||
local path = fs.concat(fs.concat(table.unpack(pathStack)), entry.name)
|
||||
|
||||
coroutine.yield(entry, levelStack)
|
||||
|
||||
if entry.isDirectory and opts.level > #levelStack then
|
||||
table.insert(iterStack, peekable(list(path)))
|
||||
table.insert(pathStack, entry.name)
|
||||
table.insert(levelStack, not not iterStack[#iterStack]:peek())
|
||||
end
|
||||
else
|
||||
table.remove(iterStack)
|
||||
table.remove(pathStack)
|
||||
table.remove(levelStack)
|
||||
end
|
||||
until #iterStack == 0
|
||||
end
|
||||
|
||||
local function dig(roots)
|
||||
return coroutine.wrap(function()
|
||||
for _, root in ipairs(roots) do
|
||||
digRoot(root)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local function nod(n) -- from /lib/core/full_ls.lua
|
||||
return n and (tostring(n):gsub("(%.[0-9]+)0+$","%1")) or "0"
|
||||
end
|
||||
|
||||
local function formatFSize(size) -- from /lib/core/full_ls.lua
|
||||
if not opts.h and not opts["human-readable"] and not opts.si then
|
||||
return tostring(size)
|
||||
end
|
||||
|
||||
local sizes = {"", "K", "M", "G"}
|
||||
local unit = 1
|
||||
local power = opts.si and 1000 or 1024
|
||||
|
||||
while size > power and unit < #sizes do
|
||||
unit = unit + 1
|
||||
size = size / power
|
||||
end
|
||||
|
||||
return nod(math.floor(size*10)/10)..sizes[unit]
|
||||
end
|
||||
|
||||
local function pad(txt) -- from /lib/core/full_ls.lua
|
||||
txt = tostring(txt)
|
||||
return #txt >= 2 and txt or "0" .. txt
|
||||
end
|
||||
|
||||
local function formatTime(epochms) -- from /lib/core/full_ls.lua
|
||||
local month_names = {"January","February","March","April","May","June",
|
||||
"July","August","September","October","November","December"}
|
||||
|
||||
if epochms == 0 then return "" end
|
||||
|
||||
local d = os.date("*t", epochms)
|
||||
local day, hour, min, sec = nod(d.day), pad(nod(d.hour)), pad(nod(d.min)), pad(nod(d.sec))
|
||||
|
||||
if opts["full-time"] then
|
||||
return string.format("%s-%s-%s %s:%s:%s ", d.year, pad(nod(d.month)), pad(day), hour, min, sec)
|
||||
else
|
||||
return string.format("%s %+2s %+2s:%+2s ", month_names[d.month]:sub(1,3), day, hour, pad(min))
|
||||
end
|
||||
end
|
||||
|
||||
local function writeEntry(entry, levelStack)
|
||||
for i, hasNext in ipairs(levelStack) do
|
||||
if opts.i then break end
|
||||
|
||||
if i == #levelStack then
|
||||
if hasNext then
|
||||
io.write("├── ")
|
||||
else
|
||||
io.write("└── ")
|
||||
end
|
||||
else
|
||||
if hasNext then
|
||||
io.write("│ ")
|
||||
else
|
||||
io.write(" ")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if opts.l then
|
||||
io.write("[")
|
||||
|
||||
io.write(entry.isDirectory and "d" or entry.isLink and "l" or "f", "-")
|
||||
io.write("r", entry.fs.isReadOnly() and "-" or "w", " ")
|
||||
|
||||
io.write(formatFSize(entry.size), " ")
|
||||
|
||||
io.write(formatTime(entry.time))
|
||||
io.write("] ")
|
||||
end
|
||||
|
||||
if opts.Q then io.write('"') end
|
||||
|
||||
if opts.color == "always" then
|
||||
io.write("\27[" .. colorize(entry) .. "m")
|
||||
end
|
||||
|
||||
if opts.f then
|
||||
io.write(entry.path)
|
||||
else
|
||||
io.write(entry.name)
|
||||
end
|
||||
|
||||
if opts.color == "always" then
|
||||
io.write("\27[0m")
|
||||
end
|
||||
|
||||
if opts.p and entry.isDirectory then
|
||||
io.write("/")
|
||||
end
|
||||
|
||||
if opts.Q then io.write('"') end
|
||||
io.write("\n")
|
||||
end
|
||||
|
||||
local function writeCount(dirs, files)
|
||||
io.write("\n")
|
||||
io.write(dirs, " director", dirs == 1 and "y" or "ies")
|
||||
io.write(", ")
|
||||
io.write(files, " file", files == 1 and "" or "s")
|
||||
io.write("\n")
|
||||
end
|
||||
|
||||
local dirs, files = 0, 0
|
||||
|
||||
local roots = {}
|
||||
for _, arg in ipairs(args) do
|
||||
local path = shell.resolve(arg)
|
||||
local real, reason = fs.realPath(path)
|
||||
if not real then
|
||||
die("cannot access ", path, ": ", reason or "unknown error")
|
||||
elseif not fs.exists(path) then
|
||||
die("cannot access ", path, ":", "No such file or directory")
|
||||
else
|
||||
table.insert(roots, real)
|
||||
end
|
||||
end
|
||||
|
||||
for entry, levelStack in dig(roots) do
|
||||
if opts.R or #levelStack > 0 then
|
||||
if entry.isDirectory then
|
||||
dirs = dirs + 1
|
||||
else
|
||||
files = files + 1
|
||||
end
|
||||
end
|
||||
writeEntry(entry, levelStack)
|
||||
yieldopt()
|
||||
end
|
||||
|
||||
if not opts.C then
|
||||
writeCount(dirs, files)
|
||||
end
|
||||
|
||||
7
shellex/.package
Normal file
7
shellex/.package
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
title = 'Shell utilities',
|
||||
repository = 'kepler155c/opus-apps/{{OPUS_BRANCH}}/shellex',
|
||||
description = [[Experimental!
|
||||
Linux style shell commands: grep, cat, touch, df, etc ]],
|
||||
licence = 'MIT',
|
||||
}
|
||||
50
shellex/apis/glob.lua
Normal file
50
shellex/apis/glob.lua
Normal file
@@ -0,0 +1,50 @@
|
||||
local GtoP = require('shellex.globtopattern')
|
||||
|
||||
local Glob = { }
|
||||
|
||||
local fs = _G.fs
|
||||
|
||||
local function splitpath(path)
|
||||
local parts = { }
|
||||
for match in string.gmatch(path, "[^/]+") do
|
||||
table.insert(parts, match)
|
||||
end
|
||||
return parts
|
||||
end
|
||||
|
||||
function Glob.matches(path, spec)
|
||||
local t = { }
|
||||
local ss = splitpath(spec)
|
||||
local abs = string.sub(spec, 1, 1) == '/'
|
||||
|
||||
local function dirMatches(dir, i)
|
||||
local files = fs.list(dir)
|
||||
local s = GtoP.globtopattern(ss[i])
|
||||
|
||||
for _, f in pairs(files) do
|
||||
if f:match(s) then
|
||||
local fp = fs.combine(dir, f)
|
||||
if not ss[i + 1] then
|
||||
table.insert(t, '/' .. fp)
|
||||
elseif ss[i + 1] and fs.isDir(fp) then
|
||||
dirMatches(fp, i + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
path = '/' .. fs.combine('', path) -- normalize
|
||||
|
||||
dirMatches(abs and '' or path, 1)
|
||||
|
||||
if not abs then
|
||||
local len = path == '/' and #path + 1 or #path + 2
|
||||
for k, v in pairs(t) do
|
||||
t[k] = v:sub(len)
|
||||
end
|
||||
end
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
return Glob
|
||||
119
shellex/apis/globtopattern.lua
Normal file
119
shellex/apis/globtopattern.lua
Normal file
@@ -0,0 +1,119 @@
|
||||
-- see: https://github.com/davidm/lua-glob-pattern
|
||||
local M = {_TYPE='module', _NAME='globtopattern', _VERSION='0.2.1.20120406'}
|
||||
|
||||
function M.globtopattern(g)
|
||||
-- Some useful references:
|
||||
-- - apr_fnmatch in Apache APR. For example,
|
||||
-- http://apr.apache.org/docs/apr/1.3/group__apr__fnmatch.html
|
||||
-- which cites POSIX 1003.2-1992, section B.6.
|
||||
|
||||
local p = "^" -- pattern being built
|
||||
local i = 0 -- index in g
|
||||
local c -- char at index i in g.
|
||||
|
||||
-- unescape glob char
|
||||
local function unescape()
|
||||
if c == '\\' then
|
||||
i = i + 1; c = g:sub(i,i)
|
||||
if c == '' then
|
||||
p = '[^]'
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- escape pattern char
|
||||
local function escape(c)
|
||||
return c:match("^%w$") and c or '%' .. c
|
||||
end
|
||||
|
||||
-- Convert tokens at end of charset.
|
||||
local function charset_end()
|
||||
while 1 do
|
||||
if c == '' then
|
||||
p = '[^]'
|
||||
return false
|
||||
elseif c == ']' then
|
||||
p = p .. ']'
|
||||
break
|
||||
else
|
||||
if not unescape() then break end
|
||||
local c1 = c
|
||||
i = i + 1; c = g:sub(i,i)
|
||||
if c == '' then
|
||||
p = '[^]'
|
||||
return false
|
||||
elseif c == '-' then
|
||||
i = i + 1; c = g:sub(i,i)
|
||||
if c == '' then
|
||||
p = '[^]'
|
||||
return false
|
||||
elseif c == ']' then
|
||||
p = p .. escape(c1) .. '%-]'
|
||||
break
|
||||
else
|
||||
if not unescape() then break end
|
||||
p = p .. escape(c1) .. '-' .. escape(c)
|
||||
end
|
||||
elseif c == ']' then
|
||||
p = p .. escape(c1) .. ']'
|
||||
break
|
||||
else
|
||||
p = p .. escape(c1)
|
||||
i = i - 1 -- put back
|
||||
end
|
||||
end
|
||||
i = i + 1; c = g:sub(i,i)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Convert tokens in charset.
|
||||
local function charset()
|
||||
i = i + 1; c = g:sub(i,i)
|
||||
if c == '' or c == ']' then
|
||||
p = '[^]'
|
||||
return false
|
||||
elseif c == '^' or c == '!' then
|
||||
i = i + 1; c = g:sub(i,i)
|
||||
if c == ']' then
|
||||
-- ignored
|
||||
else
|
||||
p = p .. '[^'
|
||||
if not charset_end() then return false end
|
||||
end
|
||||
else
|
||||
p = p .. '['
|
||||
if not charset_end() then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Convert tokens.
|
||||
while 1 do
|
||||
i = i + 1; c = g:sub(i,i)
|
||||
if c == '' then
|
||||
p = p .. '$'
|
||||
break
|
||||
elseif c == '?' then
|
||||
p = p .. '.'
|
||||
elseif c == '*' then
|
||||
p = p .. '.*'
|
||||
elseif c == '[' then
|
||||
if not charset() then break end
|
||||
elseif c == '\\' then
|
||||
i = i + 1; c = g:sub(i,i)
|
||||
if c == '' then
|
||||
p = p .. '\\$'
|
||||
break
|
||||
end
|
||||
p = p .. escape(c)
|
||||
else
|
||||
p = p .. escape(c)
|
||||
end
|
||||
end
|
||||
return p
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -1,5 +1,5 @@
|
||||
local unicode = require("openos.unicode")
|
||||
local tx = require("openos.transforms")
|
||||
local unicode = require("shellex.unicode")
|
||||
local tx = require("shellex.transforms")
|
||||
|
||||
local text = {}
|
||||
text.internal = {}
|
||||
@@ -1,6 +1,7 @@
|
||||
local fs = require("openos.filesystem")
|
||||
local shell = require("openos.shell")
|
||||
local text = require("openos.text")
|
||||
local fs = require("shellex.filesystem")
|
||||
local glob = require('shellex.glob')
|
||||
local shell = require("shellex.shell")
|
||||
local text = require("shellex.text")
|
||||
local lib = {}
|
||||
|
||||
local function perr(ops, format, ...)
|
||||
@@ -236,28 +237,31 @@ function lib.batch(args, options)
|
||||
end
|
||||
local originalToIsDir = fs.isDirectory(ok)
|
||||
|
||||
for _, fromArg in ipairs(args) do
|
||||
-- a "contents of" copy is where src path ends in . or ..
|
||||
-- a source path ending with . is not sufficient - could be the source filename
|
||||
local contents_of
|
||||
contents_of, ok = contents_check(fromArg, options, true)
|
||||
if ok then
|
||||
-- we do not append fromPath name to toPath in case of contents_of copy
|
||||
local toPath = toArg
|
||||
if contents_of and options.cmd == "mv" then
|
||||
perr(options, "invalid move path '%s'", fromArg)
|
||||
else
|
||||
if not contents_of and originalToIsDir then
|
||||
local fromName = fs.name(fromArg)
|
||||
if fromName then
|
||||
toPath = toPath .. "/" .. fromName
|
||||
for _, arg in ipairs(args) do
|
||||
local files = glob.matches(shell.getWorkingDirectory(), arg)
|
||||
for _, fromArg in pairs(files) do
|
||||
-- a "contents of" copy is where src path ends in . or ..
|
||||
-- a source path ending with . is not sufficient - could be the source filename
|
||||
local contents_of
|
||||
contents_of, ok = contents_check(fromArg, options, true)
|
||||
if ok then
|
||||
-- we do not append fromPath name to toPath in case of contents_of copy
|
||||
local toPath = toArg
|
||||
if contents_of and options.cmd == "mv" then
|
||||
perr(options, "invalid move path '%s'", fromArg)
|
||||
else
|
||||
if not contents_of and originalToIsDir then
|
||||
local fromName = fs.name(fromArg)
|
||||
if fromName then
|
||||
toPath = toPath .. "/" .. fromName
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local result, reason = lib.recurse(fromArg, toPath, options, origin, true)
|
||||
local result, reason = lib.recurse(fromArg, toPath, options, origin, true)
|
||||
|
||||
if not result then
|
||||
perr(options, reason)
|
||||
if not result then
|
||||
perr(options, reason)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
local lib={}
|
||||
lib.internal={}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local shell = require("openos.shell")
|
||||
local fs = require("openos.filesystem")
|
||||
local shell = require("shellex.shell")
|
||||
local fs = require("shellex.filesystem")
|
||||
|
||||
local args = shell.parse(...)
|
||||
local ec = 0
|
||||
@@ -1,5 +1,5 @@
|
||||
local shell = require("openos.shell")
|
||||
local transfer = require("openos.transfer")
|
||||
local shell = require("shellex.shell")
|
||||
local transfer = require("shellex.transfer")
|
||||
|
||||
local args, options = shell.parse(...)
|
||||
options.h = options.h or options.help
|
||||
@@ -1,6 +1,6 @@
|
||||
local fs = require("openos.filesystem")
|
||||
local shell = require("openos.shell")
|
||||
local text = require("openos.text")
|
||||
local fs = require("shellex.filesystem")
|
||||
local shell = require("shellex.shell")
|
||||
local text = require("shellex.text")
|
||||
|
||||
local args, options = shell.parse(...)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
local tty = require("openos.tty")
|
||||
local tty = require("shellex.tty")
|
||||
|
||||
local args = {...}
|
||||
local gpu = tty.gpu()
|
||||
@@ -1,5 +1,6 @@
|
||||
local shell = require("openos.shell")
|
||||
local fs = require("openos.filesystem")
|
||||
local fs = require("shellex.filesystem")
|
||||
local glob = require('shellex.glob')
|
||||
local shell = require("shellex.shell")
|
||||
|
||||
local args, options = shell.parse(...)
|
||||
if #args == 0 then
|
||||
@@ -107,22 +108,24 @@ local function visitor(rpath)
|
||||
end
|
||||
|
||||
for _,arg in ipairs(args) do
|
||||
local path = shell.resolve(arg)
|
||||
|
||||
if not fs.exists(path) then
|
||||
io.stderr:write(string.format("du: cannot access '%s': no such file or directory\n", arg))
|
||||
return 1
|
||||
else
|
||||
if fs.isDirectory(path) then
|
||||
local total = visitor(arg)
|
||||
|
||||
if bSummary then
|
||||
printSize(total, arg)
|
||||
end
|
||||
elseif fs.isLink(path) then
|
||||
printSize(0, arg)
|
||||
local files = glob.matches(shell.getWorkingDirectory(), arg)
|
||||
for _, v in pairs(files) do
|
||||
local path = shell.resolve(v)
|
||||
if not fs.exists(path) then
|
||||
io.stderr:write(string.format("du: cannot access '%s': no such file or directory\n", v))
|
||||
return 1
|
||||
else
|
||||
printSize(fs.size(path), arg)
|
||||
if fs.isDirectory(path) then
|
||||
local total = visitor(v)
|
||||
|
||||
if bSummary then
|
||||
printSize(total, v)
|
||||
end
|
||||
elseif fs.isLink(path) then
|
||||
printSize(0, v)
|
||||
else
|
||||
printSize(fs.size(path), v)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,6 +1,6 @@
|
||||
local shell = require("openos.shell")
|
||||
local fs = require("openos.filesystem")
|
||||
local text = require("openos.text")
|
||||
local shell = require("shellex.shell")
|
||||
local fs = require("shellex.filesystem")
|
||||
local text = require("shellex.text")
|
||||
|
||||
local USAGE =
|
||||
[===[Usage: find [path] [--type=[dfs]] [--[i]name=EXPR]
|
||||
@@ -6,10 +6,11 @@ https://raw.githubusercontent.com/OpenPrograms/Wobbo-Programs/master/grep/grep.l
|
||||
-- POSIX grep for OpenComputers
|
||||
-- one difference is that this version uses Lua regex, not POSIX regex.
|
||||
|
||||
local fs = require("openos.filesystem")
|
||||
local shell = require("openos.shell")
|
||||
local tty = require("openos.tty")
|
||||
local computer = require("openos.computer")
|
||||
local computer = require("shellex.computer")
|
||||
local fs = require("shellex.filesystem")
|
||||
local glob = require('shellex.glob')
|
||||
local shell = require("shellex.shell")
|
||||
local tty = require("shellex.tty")
|
||||
|
||||
-- Process the command line arguments
|
||||
|
||||
@@ -28,8 +29,14 @@ for more information, run: man grep
|
||||
]])
|
||||
end
|
||||
|
||||
local PATTERNS = {args[1]}
|
||||
local FILES = {select(2, table.unpack(args))}
|
||||
local PATTERNS = { table.remove(args, 1) }
|
||||
local FILES = { }
|
||||
for _, arg in pairs(args) do
|
||||
local files = glob.matches(shell.getWorkingDirectory(), arg)
|
||||
for _, v in pairs(files) do
|
||||
table.insert(FILES, v)
|
||||
end
|
||||
end
|
||||
|
||||
local LABEL_COLOR = 0xb000b0
|
||||
local LINE_NUM_COLOR = 0x00FF00
|
||||
@@ -167,7 +174,7 @@ end
|
||||
if search_recursively then
|
||||
local files = {}
|
||||
for _,arg in ipairs(FILES) do
|
||||
if fs.isDirectory(arg) then
|
||||
if fs.isDirectory(shell.resolve(arg)) then
|
||||
getAllFiles(arg, files)
|
||||
else
|
||||
files[#files+1]=arg
|
||||
@@ -1,5 +1,4 @@
|
||||
local shell = require("openos.shell")
|
||||
local fs = require("openos.filesystem")
|
||||
local shell = require("shellex.shell")
|
||||
|
||||
local args, options = shell.parse(...)
|
||||
local error_code = 0
|
||||
@@ -1,6 +1,6 @@
|
||||
local os = _G.os
|
||||
|
||||
local shell = require("openos.shell")
|
||||
local shell = require("shellex.shell")
|
||||
local args = shell.parse(...)
|
||||
local hostname = args[1]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
local keys = require("openos.keyboard").keys
|
||||
local shell = require("openos.shell")
|
||||
local unicode = require("openos.unicode")
|
||||
local term = require("openos.term") -- using term for negative scroll feature
|
||||
local keys = require("shellex.keyboard").keys
|
||||
local shell = require("shellex.shell")
|
||||
local unicode = require("shellex.unicode")
|
||||
local term = require("shellex.term") -- using term for negative scroll feature
|
||||
|
||||
local args, ops = shell.parse(...)
|
||||
if #args > 1 then
|
||||
@@ -1,5 +1,5 @@
|
||||
local fs = require("openos.filesystem")
|
||||
local shell = require("openos.shell")
|
||||
local fs = require("shellex.filesystem")
|
||||
local shell = require("shellex.shell")
|
||||
|
||||
local args = shell.parse(...)
|
||||
if #args == 0 then
|
||||
@@ -1,9 +1,10 @@
|
||||
local fs = require("openos.filesystem")
|
||||
local shell = require("openos.shell")
|
||||
local tty = require("openos.tty")
|
||||
local unicode = require("openos.unicode")
|
||||
local tx = require("openos.transforms")
|
||||
local text = require("openos.text")
|
||||
local fs = require("shellex.filesystem")
|
||||
local glob = require('shellex.glob')
|
||||
local shell = require("shellex.shell")
|
||||
local tty = require("shellex.tty")
|
||||
local unicode = require("shellex.unicode")
|
||||
local tx = require("shellex.transforms")
|
||||
local text = require("shellex.text")
|
||||
|
||||
local dirsArg, ops = shell.parse(...)
|
||||
|
||||
@@ -42,7 +43,6 @@ local function stat(names, index)
|
||||
end
|
||||
local info = {}
|
||||
info.key = name
|
||||
info._path = name
|
||||
info.path = name:sub(1, 1) == "/" and "" or names.path
|
||||
info.full_path = fs.concat(info.path, name)
|
||||
info.isDir = fs.isDirectory(info.full_path)
|
||||
@@ -248,7 +248,6 @@ local function display(names)
|
||||
local info = stat(names, index)
|
||||
local file_type = info.isLink and 'l' or info.isDir and 'd' or 'f'
|
||||
local link_target = info.isLink and string.format(" -> %s", info.link:gsub("/+$", "") .. (info.isDir and "/" or "")) or ""
|
||||
_G._p = info
|
||||
local write_mode = info.fs.isReadOnly() and '-' or 'w'
|
||||
local size = formatSize(info.size)
|
||||
local format = "%s-r%s %+"..tostring(max_size_width)..'s '
|
||||
@@ -345,6 +344,7 @@ local function displayDirList(dirs)
|
||||
end
|
||||
end
|
||||
end
|
||||
--[[
|
||||
local dir_set, file_set = {}, {path=shell.getWorkingDirectory()}
|
||||
for _,dir in ipairs(dirsArg) do
|
||||
local path = shell.resolve(dir)
|
||||
@@ -360,6 +360,23 @@ for _,dir in ipairs(dirsArg) do
|
||||
table.insert(file_set, dir)
|
||||
end
|
||||
end
|
||||
]]
|
||||
local dir_set, file_set = {}, {path=shell.getWorkingDirectory()}
|
||||
for _,dir in ipairs(dirsArg) do
|
||||
local path = shell.resolve(dir)
|
||||
if fs.isDirectory(path) then
|
||||
table.insert(dir_set, dir)
|
||||
else
|
||||
local files = glob.matches(shell.getWorkingDirectory(), dir)
|
||||
for _, v in pairs(files) do
|
||||
table.insert(file_set, v)
|
||||
end
|
||||
if #files == 0 then
|
||||
local access_msg = "cannot access " .. tostring(dir) .. ": "
|
||||
perr(access_msg .. "No such file or directory")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
io.output():setvbuf("line")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local shell = require("openos.shell")
|
||||
local transfer = require("openos.transfer")
|
||||
local shell = require("shellex.shell")
|
||||
local transfer = require("shellex.transfer")
|
||||
|
||||
local args, options = shell.parse(...)
|
||||
options.h = options.h or options.help
|
||||
@@ -1,5 +1,6 @@
|
||||
local fs = require("openos.filesystem")
|
||||
local shell = require("openos.shell")
|
||||
local fs = require("shellex.filesystem")
|
||||
local glob = require('shellex.glob')
|
||||
local shell = require("shellex.shell")
|
||||
|
||||
local function usage()
|
||||
print("Usage: rm [options] <filename1> [<filename2> [...]]"..[[
|
||||
@@ -40,14 +41,14 @@ local function pout(...)
|
||||
end
|
||||
|
||||
local metas = {}
|
||||
local remove
|
||||
|
||||
-- promptLevel 3 done before fs.exists
|
||||
-- promptLevel 1 asks for each, displaying fs.exists on hit as it visits
|
||||
|
||||
local function _path(m) return shell.resolve(m.rel) end
|
||||
local function _link(m) return fs.isLink(_path(m)) end
|
||||
local function _exists(m) return _link(m) or fs.exists(_path(m)) end
|
||||
local function _dir(m) return not _link(m) and fs.isDirectory(_path(m)) end
|
||||
local function _exists(m) return fs.exists(_path(m)) end
|
||||
local function _dir(m) return fs.isDirectory(_path(m)) end
|
||||
local function _readonly(m) return not _exists(m) or fs.get(_path(m)).isReadOnly() end
|
||||
local function _empty(m) return _exists(m) and _dir(m) and (fs.list(_path(m))==nil) end
|
||||
|
||||
@@ -94,7 +95,7 @@ local function remove_all(parent)
|
||||
return all_ok
|
||||
end
|
||||
|
||||
local function remove(meta)
|
||||
remove = function(meta)
|
||||
if not remove_all(meta) then
|
||||
return false
|
||||
end
|
||||
@@ -140,7 +141,10 @@ local function remove(meta)
|
||||
end
|
||||
|
||||
for _,arg in ipairs(args) do
|
||||
metas[#metas+1] = createMeta(arg, arg)
|
||||
local files = glob.matches(shell.getWorkingDirectory(), arg)
|
||||
for _, v in pairs(files) do
|
||||
metas[#metas+1] = createMeta(v, v)
|
||||
end
|
||||
end
|
||||
|
||||
if promptLevel == 3 and #metas > 3 then
|
||||
@@ -1,6 +1,6 @@
|
||||
local shell = require("openos.shell")
|
||||
local fs = require("openos.filesystem")
|
||||
local text = require("openos.text")
|
||||
local shell = require("shellex.shell")
|
||||
local fs = require("shellex.filesystem")
|
||||
local text = require("shellex.text")
|
||||
|
||||
local args, options = shell.parse(...)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local computer = require('openos.computer')
|
||||
local sh = require('openos.sh')
|
||||
local computer = require('shellex.computer')
|
||||
local sh = require('shellex.sh')
|
||||
|
||||
local real_before, cpu_before = computer.uptime(), os.clock()
|
||||
local cmd_result = 0
|
||||
@@ -1,6 +1,6 @@
|
||||
--[[Lua implementation of the UN*X touch command--]]
|
||||
local shell = require("openos.shell")
|
||||
local fs = require("openos.filesystem")
|
||||
local shell = require("shellex.shell")
|
||||
local fs = require("shellex.filesystem")
|
||||
|
||||
local args, options = shell.parse(...)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
local shell = require("openos.shell")
|
||||
local shell = require("shellex.shell")
|
||||
|
||||
local args = shell.parse(...)
|
||||
if #args == 0 then
|
||||
Reference in New Issue
Block a user