New utils
This commit is contained in:
+97
-1
@@ -166,10 +166,12 @@ async function walk(ctx, dir, o, curDepth) {
|
||||
const nameOk = !o.nameRe || o.nameRe.test(n)
|
||||
let match = pathOk && nameOk && (!o.wantType || st.type === o.wantType)
|
||||
if (match && o.mtimeSpec) match = match && findMatchMtime(st, o.mtimeSpec)
|
||||
if (match && o.newerThanMs != null) match = match && st.mtimeMs > o.newerThanMs
|
||||
if (match && o.newerThanMs != null)
|
||||
match = match && st.mtimeMs > o.newerThanMs
|
||||
if (match && o.wantEmpty) {
|
||||
match = match && (await findIsEmpty(ctx, path, st))
|
||||
}
|
||||
if (match && o.regexPath && !o.regexPath.test(path)) match = false
|
||||
if (match && gnuDepth >= o.minDepth) {
|
||||
if (o.doDelete) {
|
||||
if (ctx.vfs.env.BARE_OS_FIND_DELETE !== '1') {
|
||||
@@ -189,6 +191,40 @@ async function walk(ctx, dir, o, curDepth) {
|
||||
ctx.exitCode = 1
|
||||
}
|
||||
}
|
||||
} else if (o.execTemplate && o.execTemplate.length) {
|
||||
if (typeof ctx.runBinCommand !== 'function') {
|
||||
const stw = /** @type {{ noRun?: boolean }} */ (o.deleteState)
|
||||
if (!stw.noRun) {
|
||||
ctx.console.error('find: -exec requires ctx.runBinCommand')
|
||||
stw.noRun = true
|
||||
}
|
||||
ctx.exitCode = 1
|
||||
} else if (o.execCount >= o.execMax) {
|
||||
const stw = /** @type {{ execCap?: boolean }} */ (o.deleteState)
|
||||
if (!stw.execCap) {
|
||||
ctx.console.error(
|
||||
'find: -exec/-ok: invocation limit (' +
|
||||
o.execMax +
|
||||
') exceeded (raise BARE_OS_FIND_EXEC_MAX)'
|
||||
)
|
||||
stw.execCap = true
|
||||
}
|
||||
ctx.exitCode = 1
|
||||
} else {
|
||||
const ok =
|
||||
!o.execUseOk ||
|
||||
ctx.vfs.env.BARE_OS_FIND_OK === '1' ||
|
||||
ctx.vfs.env.BARE_OS_FIND_OK === 'true'
|
||||
if (o.execUseOk && !ok) {
|
||||
/* skip without running */
|
||||
} else {
|
||||
const subst = o.execTemplate.map((arg) =>
|
||||
arg === '{}' ? path : arg.split('{}').join(path)
|
||||
)
|
||||
o.execCount++
|
||||
await ctx.runBinCommand(subst)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
findEmitLine(ctx, path, o.print0)
|
||||
}
|
||||
@@ -219,6 +255,11 @@ async function run(ctx, argv) {
|
||||
let prunePath = null
|
||||
let wantEmpty = false
|
||||
let doDelete = false
|
||||
/** @type {string[] | null} */
|
||||
let execTemplate = null
|
||||
let execUseOk = false
|
||||
/** @type {string | null} */
|
||||
let regexPathStr = null
|
||||
const rest = []
|
||||
for (let i = 1; i < argv.length; i++) {
|
||||
const a = argv[i]
|
||||
@@ -281,6 +322,39 @@ async function run(ctx, argv) {
|
||||
doDelete = true
|
||||
continue
|
||||
}
|
||||
if ((a === '-exec' || a === '-ok') && argv[i + 1]) {
|
||||
execUseOk = a === '-ok'
|
||||
i++
|
||||
const parts = []
|
||||
while (i < argv.length && argv[i] !== ';') {
|
||||
parts.push(argv[i++])
|
||||
}
|
||||
if (i >= argv.length || argv[i] !== ';') {
|
||||
ctx.console.error('find: ' + a + ' must be terminated with ;')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
i++
|
||||
if (!parts.length) {
|
||||
ctx.console.error('find: empty ' + a)
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
execTemplate = parts
|
||||
continue
|
||||
}
|
||||
if (a === '-regex' && argv[i + 1]) {
|
||||
const pat = argv[++i]
|
||||
try {
|
||||
new RegExp(pat)
|
||||
regexPathStr = pat
|
||||
} catch {
|
||||
ctx.console.error('find: invalid -regex')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (a === '--') {
|
||||
rest.push(...argv.slice(i + 1))
|
||||
break
|
||||
@@ -333,6 +407,23 @@ async function run(ctx, argv) {
|
||||
if (prunePath) {
|
||||
pruneAbs = ctx.vfs.resolveLogical(prunePath).replace(/\/+$/, '') || '/'
|
||||
}
|
||||
/** @type {RegExp | null} */
|
||||
let regexPath = null
|
||||
if (regexPathStr) {
|
||||
try {
|
||||
regexPath = new RegExp(regexPathStr)
|
||||
} catch {
|
||||
ctx.console.error('find: invalid -regex')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
}
|
||||
const execMaxRaw = ctx.vfs.env.BARE_OS_FIND_EXEC_MAX
|
||||
let execMax = 64
|
||||
if (execMaxRaw != null && String(execMaxRaw).trim() !== '') {
|
||||
const n = Number.parseInt(String(execMaxRaw), 10)
|
||||
if (Number.isFinite(n)) execMax = Math.min(4096, Math.max(1, n))
|
||||
}
|
||||
const abs = ctx.vfs.resolveLogical(root)
|
||||
const o = {
|
||||
maxDepth,
|
||||
@@ -346,6 +437,11 @@ async function run(ctx, argv) {
|
||||
pruneAbs,
|
||||
wantEmpty,
|
||||
doDelete,
|
||||
regexPath,
|
||||
execTemplate,
|
||||
execUseOk,
|
||||
execCount: 0,
|
||||
execMax,
|
||||
deleteState: {}
|
||||
}
|
||||
await walk(ctx, abs, o, 0)
|
||||
|
||||
Reference in New Issue
Block a user