Updates
This commit is contained in:
@@ -2,17 +2,10 @@
|
||||
"name": "find",
|
||||
"section": 1,
|
||||
"title": "find files",
|
||||
"synopsis": [
|
||||
"find [PATH...] [EXPRESSION]"
|
||||
],
|
||||
"description": "Walks directories and applies expressions (-name, -type, -print, -maxdepth, logical -and/-or/-not).",
|
||||
"synopsis": ["find [PATH...] [EXPRESSION]"],
|
||||
"description": "Walks directories and applies expressions (-name, -type, -print, -maxdepth, -mindepth, logical -and/-or/-not).",
|
||||
"options": [],
|
||||
"keywords": [
|
||||
"find",
|
||||
"directory",
|
||||
"walk",
|
||||
"search"
|
||||
],
|
||||
"keywords": ["find", "directory", "walk", "search"],
|
||||
"bareOsNotes": "Expression syntax is a simplified subset.",
|
||||
"examples": [
|
||||
{
|
||||
@@ -27,6 +20,10 @@
|
||||
"caption": "max depth",
|
||||
"code": "find . -maxdepth 2 -type f"
|
||||
},
|
||||
{
|
||||
"caption": "skip top directory level (GNU-like -mindepth 2)",
|
||||
"code": "find . -mindepth 2 -type f"
|
||||
},
|
||||
{
|
||||
"caption": "OR names",
|
||||
"code": "find . \\( -name \"*.c\" -o -name \"*.h\" \\)"
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
async function walk(ctx, dir, nameRe, wantType, maxDepth, curDepth) {
|
||||
/**
|
||||
* curDepth is distance from the search root directory (0 at the initial path).
|
||||
* Printed paths use gnu-like depth curDepth + 1 (immediate children of the root are depth 1).
|
||||
*/
|
||||
async function walk(ctx, dir, nameRe, wantType, maxDepth, minDepth, curDepth) {
|
||||
if (maxDepth >= 0 && curDepth > maxDepth) return
|
||||
let names
|
||||
try {
|
||||
@@ -16,15 +20,21 @@ async function walk(ctx, dir, nameRe, wantType, maxDepth, curDepth) {
|
||||
continue
|
||||
}
|
||||
if (!st) continue
|
||||
const gnuDepth = curDepth + 1
|
||||
if (!nameRe || nameRe.test(n)) {
|
||||
if (!wantType || st.type === wantType) ctx.console.log(path)
|
||||
if (!wantType || st.type === wantType) {
|
||||
if (gnuDepth >= minDepth) ctx.console.log(path)
|
||||
}
|
||||
}
|
||||
if (st.type === 'directory') await walk(ctx, path, nameRe, wantType, maxDepth, curDepth + 1)
|
||||
if (st.type === 'directory')
|
||||
await walk(ctx, path, nameRe, wantType, maxDepth, minDepth, curDepth + 1)
|
||||
}
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
let maxDepth = -1
|
||||
/** Minimum path depth below the search root (1 = default; same as GNU -mindepth 1 for tree walks). */
|
||||
let minDepth = 1
|
||||
/** @type {string | null} */
|
||||
let nameGlob = null
|
||||
/** @type {'file' | 'directory' | 'symlink' | null} */
|
||||
@@ -36,6 +46,11 @@ async function run(ctx, argv) {
|
||||
maxDepth = Number.parseInt(argv[++i], 10)
|
||||
continue
|
||||
}
|
||||
if (a === '-mindepth' && argv[i + 1]) {
|
||||
minDepth = Number.parseInt(argv[++i], 10)
|
||||
if (!Number.isFinite(minDepth) || minDepth < 1) minDepth = 1
|
||||
continue
|
||||
}
|
||||
if (a === '-name' && argv[i + 1]) {
|
||||
nameGlob = argv[++i]
|
||||
continue
|
||||
@@ -61,9 +76,12 @@ async function run(ctx, argv) {
|
||||
const root = rest[0] || '.'
|
||||
let nameRe = null
|
||||
if (nameGlob) {
|
||||
const esc = nameGlob.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*').replace(/\?/g, '.')
|
||||
const esc = nameGlob
|
||||
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
||||
.replace(/\*/g, '.*')
|
||||
.replace(/\?/g, '.')
|
||||
nameRe = new RegExp('^' + esc + '$')
|
||||
}
|
||||
const abs = ctx.vfs.resolveLogical(root)
|
||||
await walk(ctx, abs, nameRe, wantType, maxDepth, 0)
|
||||
await walk(ctx, abs, nameRe, wantType, maxDepth, minDepth, 0)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user