Objektbaum aus Dateisystem erstellen
Ich muss den Pfad des Verzeichnisses aus dem CL-Argument abrufen und einen Objektbaum erstellen, der die Dateistruktur des ausgewählten Verzeichnisses enthält.
Wenn es sich um eine Datei handelt, sollte der Wert true sein. Und wenn es ein Verzeichnis ist, sollte ich dasselbe für dieses Verzeichnis tun (ich denke, der beste Ansatz ist die Rekursion).
Die Ausgabe sollte ungefähr so aussehen:
{
file.txt: true,
directory: {
one.txt: true,
two.txt: true,
...
}
...
}
Bisher habe ich die Rekursionsversion davon ausprobiert, aber sie schlägt fehl und weiß nicht warum. Ich denke, das liegt daran, dass ich den asynchronen Teil meines Codes nicht richtig behandelt habe. Hier ist mein Code:
const fs = require("fs");
const basePath = process.argv[2]; //Getting the path (it works)
const result = {};
//Function to check my path is exist and it's a directory
const isDirectory = path => {
return new Promise((resolve, reject) => {
fs.lstat(path, (err, stats) => {
if (err) reject("No such file or Directory");
resolve(stats.isDirectory());
});
});
};
//Recursive function that should create the object tree of the file system
const createTree = (path, target) => {
return new Promise((resolve, reject) => {
reject("Promise Oops...");
fs.readdir(path, (err, data) => {
data.forEach(item => {
const currentLocation = `${path}/${item}`;
isDirectory(currentLocation)
.then(isDir => {
if (!isDir) {
target[item] = true;
return;
}
target[item] = {};
resolve(createTree(currentLocation, target[item]));
})
.catch(err => console.log("Oops in then..."));
});
});
});
};
//Consuming the createTree function
(async () => {
try {
const res = await createTree(basePath, result);
console.log(res);
} catch (err) {
console.log("Oops consume...");
}
})();
Antworten
Sie können fs.promisesanstelle von Callback-basierten Methoden von fs verwenden, was die Lesbarkeit verbessert und Ihnen hilft, die Fehler leicht zu finden. Sie protokollieren, was von einer createTreeundefinierten Funktion zurückgegeben wird. Sie sollten ein resultObjekt protokollieren , um das gewünschte Ergebnis zu sehen.
const fs = require("fs");
const basePath = process.argv[2]; //Getting the path (it works)
const result = {};
//Function to check my path is exist and it's a directory
const isDirectory = async (path) => {
try {
const stats = await fs.promises.lstat(path);
return stats.isDirectory();
} catch (error) {
throw new Error("No such file or Directory");
}
};
//Recursive function that should create the object tree of the file system
const createTree = async (path, target) => {
const data = await fs.promises.readdir(path);
for (const item of data) {
const currentLocation = `${path}/${item}`;
const isDir = await isDirectory(currentLocation);
if (!isDir) {
target[item] = true;
continue;
}
target[item] = {};
await createTree(currentLocation, target[item]);
}
};
//Consuming the createTree function
(async () => {
try {
await createTree(basePath, result);
console.log(result);
} catch (error) {
console.log(error.message);
}
})();
fs / versprechen und fs.Dirent
Hier ist ein effizientes, nicht blockierendes Programm, das das schnelle fs.Dirent- Objekt- und fs / versprechen- Modul von Node verwendet . Dieser Ansatz ermöglicht es Ihnen, verschwenderische fs.existoder fs.statAufrufe auf jedem Pfad zu überspringen -
// main.js
import { readdir } from "fs/promises"
import { join, basename } from "path"
async function* tokenise (path = ".")
{ yield { dir: path }
for (const dirent of await readdir(path, { withFileTypes: true }))
if (dirent.isDirectory())
yield* tokenise(join(path, dirent.name))
else
yield { file: join(path, dirent.name) }
yield { endDir: path }
}
async function parse (iter = empty())
{ const r = [{}]
for await (const e of iter)
if (e.dir)
r.unshift({})
else if (e.file)
r[0][basename(e.file)] = true
else if (e.endDir)
r[1][basename(e.endDir)] = r.shift()
return r[0]
}
async function* empty () {}
Jetzt createTreeist einfach eine Kombination aus tokeniseund parse-
const createTree = (path = ".") =>
parse(tokenise(path))
createTree(".")
.then(r => console.log(JSON.stringify(r, null, 2)))
.catch(console.error)
Lassen Sie uns einige Beispieldateien holen, damit wir sehen können, wie es funktioniert -
$ yarn add immutable # (just some example package) $ node main.js
{
".": {
"main.js": true,
"node_modules": {
".yarn-integrity": true,
"immutable": {
"LICENSE": true,
"README.md": true,
"contrib": {
"cursor": {
"README.md": true,
"__tests__": {
"Cursor.ts.skip": true
},
"index.d.ts": true,
"index.js": true
}
},
"dist": {
"immutable-nonambient.d.ts": true,
"immutable.d.ts": true,
"immutable.es.js": true,
"immutable.js": true,
"immutable.js.flow": true,
"immutable.min.js": true
},
"package.json": true
}
},
"package.json": true,
"yarn.lock": true
}
}
Ich hoffe, Sie haben diesen Beitrag genossen. Weitere Erklärungen und andere Möglichkeiten zur Verwendung von Async-Generatoren finden Sie in diesen Fragen und Antworten .