Node.js를 사용하여 파일 시스템의 디렉토리 구조를 JSON으로 변환
다음과 같은 파일 구조가 있습니다.
root
|_ fruits
|___ apple
|______images
|________ apple001.jpg
|________ apple002.jpg
|_ animals
|___ cat
|______images
|________ cat001.jpg
|________ cat002.jpg
Javascript 및 Node.js를 사용하여이 루트 디렉터리와 모든 하위 디렉터리를 듣고이 디렉터리 구조를 미러링하는 JSON을 만들고 싶습니다. 각 노드에는 유형, 이름, 경로 및 자식이 포함됩니다.
data = [
{
type: "folder",
name: "animals",
path: "/animals",
children: [
{
type: "folder",
name: "cat",
path: "/animals/cat",
children: [
{
type: "folder",
name: "images",
path: "/animals/cat/images",
children: [
{
type: "file",
name: "cat001.jpg",
path: "/animals/cat/images/cat001.jpg"
}, {
type: "file",
name: "cat001.jpg",
path: "/animals/cat/images/cat002.jpg"
}
]
}
]
}
]
}
];
다음은 coffeescript JSON입니다.
data =
[
type: "folder"
name: "animals"
path: "/animals"
children :
[
type: "folder"
name: "cat"
path: "/animals/cat"
children:
[
type: "folder"
name: "images"
path: "/animals/cat/images"
children:
[
type: "file"
name: "cat001.jpg"
path: "/animals/cat/images/cat001.jpg"
,
type: "file"
name: "cat001.jpg"
path: "/animals/cat/images/cat002.jpg"
]
]
]
]
이 json 데이터 형식을 django 뷰에서 얻는 방법은 무엇입니까? (python)
여기 스케치가 있습니다. 오류 처리는 독자를위한 연습으로 남겨집니다.
var fs = require('fs'),
path = require('path')
function dirTree(filename) {
var stats = fs.lstatSync(filename),
info = {
path: filename,
name: path.basename(filename)
};
if (stats.isDirectory()) {
info.type = "folder";
info.children = fs.readdirSync(filename).map(function(child) {
return dirTree(filename + '/' + child);
});
} else {
// Assuming it's a file. In real life it could be a symlink or
// something else!
info.type = "file";
}
return info;
}
if (module.parent == undefined) {
// node dirTree.js ~/foo/bar
var util = require('util');
console.log(util.inspect(dirTree(process.argv[2]), false, null));
}
NPM 모듈이 있습니다.
https://www.npmjs.com/package/directory-tree
디렉터리 트리를 나타내는 개체를 만듭니다.
에서:
photos
├── summer
│ └── june
│ └── windsurf.jpg
└── winter
└── january
├── ski.png
└── snowboard.jpg
에:
{
"path": "",
"name": "photos",
"type": "directory",
"children": [
{
"path": "summer",
"name": "summer",
"type": "directory",
"children": [
{
"path": "summer/june",
"name": "june",
"type": "directory",
"children": [
{
"path": "summer/june/windsurf.jpg",
"name": "windsurf.jpg",
"type": "file"
}
]
}
]
},
{
"path": "winter",
"name": "winter",
"type": "directory",
"children": [
{
"path": "winter/january",
"name": "january",
"type": "directory",
"children": [
{
"path": "winter/january/ski.png",
"name": "ski.png",
"type": "file"
},
{
"path": "winter/january/snowboard.jpg",
"name": "snowboard.jpg",
"type": "file"
}
]
}
]
}
]
}
용법
var tree = directoryTree('/some/path');
확장 프로그램으로 필터링 할 수도 있습니다.
var filteredTree = directoryTree('/some/path', ['.jpg', '.png']);
허용되는 답변은 작동하지만 동기식 이며 특히 큰 디렉토리 트리의 경우 성능을 크게 저하시킵니다.
다음 비동기 솔루션 을 사용하는 것이 좋습니다 . 더 빠르고 차단되지 않습니다. 여기
병렬 솔루션을 기반으로합니다 .
var fs = require('fs');
var path = require('path');
var diretoryTreeToObj = function(dir, done) {
var results = [];
fs.readdir(dir, function(err, list) {
if (err)
return done(err);
var pending = list.length;
if (!pending)
return done(null, {name: path.basename(dir), type: 'folder', children: results});
list.forEach(function(file) {
file = path.resolve(dir, file);
fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) {
diretoryTreeToObj(file, function(err, res) {
results.push({
name: path.basename(file),
type: 'folder',
children: res
});
if (!--pending)
done(null, results);
});
}
else {
results.push({
type: 'file',
name: path.basename(file)
});
if (!--pending)
done(null, results);
}
});
});
});
};
사용 예 :
var dirTree = ('/path/to/dir');
diretoryTreeToObj(dirTree, function(err, res){
if(err)
console.error(err);
console.log(JSON.stringify(res));
});
Miika의 솔루션을 기반으로 한 내 CS 예제 (익스프레스 포함) :
fs = require 'fs' #file system module
path = require 'path' # file path module
# returns json tree of directory structure
tree = (root) ->
# clean trailing '/'(s)
root = root.replace /\/+$/ , ""
# extract tree ring if root exists
if fs.existsSync root
ring = fs.lstatSync root
else
return 'error: root does not exist'
# type agnostic info
info =
path: root
name: path.basename(root)
# dir
if ring.isDirectory()
info.type = 'folder'
# execute for each child and call tree recursively
info.children = fs.readdirSync(root) .map (child) ->
tree root + '/' + child
# file
else if ring.isFile()
info.type = 'file'
# link
else if ring.isSymbolicLink()
info.type = 'link'
# other
else
info.type = 'unknown'
# return tree
info
# error handling
handle = (e) ->
return 'uncaught exception...'
exports.index = (req, res) ->
try
res.send tree './test/'
catch e
res.send handle e
이 프로젝트의 코드를 사용할 수 있지만 필요에 맞게 코드를 조정해야합니다.
https://github.com/NHQ/Node-FileUtils/blob/master/src/file-utils.js#L511-L593
에서:
a
|- b
| |- c
| | |- c1.txt
| |
| |- b1.txt
| |- b2.txt
|
|- d
| |
|
|- a1.txt
|- a2.txt
에:
{
b: {
"b1.txt": "a/b/b1.txt",
"b2.txt": "a/b/b2.txt",
c: {
"c1.txt": "a/b/c/c1.txt"
}
},
d: {},
"a2.txt": "a/a2.txt",
"a1.txt": "a/a1.txt"
}
하기:
new File ("a").list (function (error, files){
//files...
});
다음은 비동기 솔루션입니다.
function list(dir) {
const walk = entry => {
return new Promise((resolve, reject) => {
fs.exists(entry, exists => {
if (!exists) {
return resolve({});
}
return resolve(new Promise((resolve, reject) => {
fs.lstat(entry, (err, stats) => {
if (err) {
return reject(err);
}
if (!stats.isDirectory()) {
return resolve({
// path: entry,
// type: 'file',
name: path.basename(entry),
time: stats.mtime,
size: stats.size
});
}
resolve(new Promise((resolve, reject) => {
fs.readdir(entry, (err, files) => {
if (err) {
return reject(err);
}
Promise.all(files.map(child => walk(path.join(entry, child)))).then(children => {
resolve({
// path: entry,
// type: 'folder',
name: path.basename(entry),
time: stats.mtime,
entries: children
});
}).catch(err => {
reject(err);
});
});
}));
});
}));
});
});
}
return walk(dir);
}
디렉토리가 존재하지 않으면 오류가 발생하지 않고 빈 결과가 반환됩니다.
다음은 샘플 결과입니다.
{
"name": "root",
"time": "2017-05-09T07:46:26.740Z",
"entries": [
{
"name": "book.txt",
"time": "2017-05-09T07:24:18.673Z",
"size": 0
},
{
"name": "cheatsheet-a5.pdf",
"time": "2017-05-09T07:24:18.674Z",
"size": 262380
},
{
"name": "docs",
"time": "2017-05-09T07:47:39.507Z",
"entries": [
{
"name": "README.md",
"time": "2017-05-08T10:02:09.651Z",
"size": 19229
}
]
}
]
}
다음과 같습니다.
root
|__ book.txt
|__ cheatsheet-a5.pdf
|__ docs
|__ README.md
이 경우 'walk'lib를 사용했습니다. 루트 경로를 가져와 파일과 디렉터리를 재귀 적으로 탐색하고 노드에서 필요한 모든 정보가 포함 된 디렉터리 / 파일 이벤트를 내 보냅니다. 해당 구현을 확인하십시오->
const walk = require('walk');
class FsTree {
constructor(){
}
/**
* @param rootPath
* @returns {Promise}
*/
getFileSysTree(rootPath){
return new Promise((resolve, reject)=>{
const root = rootPath || __dirname; // if there's no rootPath use exec location
const tree = [];
const nodesMap = {};
const walker = walk.walk(root, { followLinks: false}); // filter doesn't work well
function addNode(node, path){
if ( node.name.indexOf('.') === 0 || path.indexOf('/.') >= 0){ // ignore hidden files
return;
}
var relativePath = path.replace(root,'');
node.path = relativePath + '/' + node.name;
nodesMap[node.path] = node;
if ( relativePath.length === 0 ){ //is root
tree.push(node);
return;
}
node.parentPath = node.path.substring(0,node.path.lastIndexOf('/'));
const parent = nodesMap[node.parentPath];
parent.children.push(node);
}
walker.on('directory', (path, stats, next)=>{
addNode({ name: stats.name, type:'dir',children:[]}, path);
next();
});
walker.on('file', (path,stats,next)=>{
addNode({name:stats.name, type:'file'},path);
next();
});
walker.on('end',()=>{
resolve(tree);
});
walker.on('errors', (root, nodeStatsArray, next) => {
reject(nodeStatsArray);
next();
});
});
}
}
const fsTreeFetcher = new FsTree();
fsTreeFetcher.getFileSysTree(__dirname).then((result)=>{
console.log(result);
});
다음은 해당 작업에 가장 적합한 모듈입니다.
많은 사용자 정의 옵션이 있으며 결과는 다음과 같습니다.
{
"name": "sample",
"path": "D:/Github/dree/test/sample",
"relativePath": ".",
"type": "directory",
"size": "1.79 MB",
"children": [
{
"name": "backend",
"path": "D:/Github/dree/test/sample/backend",
"relativePath": "backend",
"type": "directory",
"size": "1.79 MB",
"children": [
{
"name": "firebase.json",
"path": "D:/Github/dree/test/sample/backend/firebase.json",
"relativePath": "backend/firebase.json",
"type": "file",
"extension": "json",
"size": "29 B"
},
{
"name": "server",
"path": "D:/Github/dree/test/sample/backend/server",
"relativePath": "backend/server",
"type": "directory",
"size": "1.79 MB",
"children": [
{
"name": "server.ts",
"path": "D:/Github/dree/test/sample/backend/server/server.ts",
"relativePath": "backend/server/server.ts",
"type": "file",
"extension": "ts",
"size": "1.79 MB"
}
]
}
]
}
]
}
다음과 같이 문자열도 반환 될 수 있습니다.
sample
└─> backend
├── firebase.json
├── hello.txt
└─> server
└── server.ts
예:
const dree = require('dree');
const options = {
stat: false,
normalize: true,
followLinks: true,
size: true,
depth: 5,
exclude: [/dir_to_exclude/, /another_dir_to_exclude/ ],
extensions: [ 'txt', 'jpg' ]
};
const tree = dree.scan('./folder', options);
'Development Tip' 카테고리의 다른 글
Linux에서 getch () 및 getche ()에 해당하는 것은 무엇입니까? (0) | 2020.12.15 |
---|---|
Pylint의 파일 수준에서 "missing docstring"경고를 비활성화하려면 어떻게해야합니까? (0) | 2020.12.15 |
C # 보호 메서드 단위 테스트 (0) | 2020.12.15 |
Haskell에 암시 적 병렬성이없는 이유는 무엇입니까? (0) | 2020.12.15 |
LocationClient getLastLocation () 반환 null (0) | 2020.12.15 |