NodeJS/fs.readdir - Ignore certain subdirectories when scanning for a specific set of subdirectories (closed) - node.js

Say we have a working directory containing subdirectories like so:
<workDir>
|— UselessFolder
|— NotThisFolder
|— SkipThisFolder
|— UsefulFolder
|— UsefulFolder2
|— UsefulFolder3
Is there a way that I can ignore the UselessFolder, NotThisFolder & SkipThisFolder subdirectories while scanning the working directory with fs.readdir?
The goal of the function that requires this, is to find the very last instance of the UsefulFolder subdirectories and do work with them later on. The function works fine most of the time, but it breaks in some cases due to the subfolders that I want to ignore that were stated above, I know this because if I completely remove the subfolders I want my function to ignore, the function will work fine, but in my case I can't delete any of the subdirectories within the working directory, so the only option is to ignore the ones I don't care about.
The code I'm currently using in my function to read the working directory and list its subdirectories is the following:
var workDir = '/home/user/workDir';
fs.readdir(workDir, { withFileTypes: true }, (error, files) => {
if (error) {
console.log('An error occured while reading the working directory! \n\n')
console.log('Reason: ' + error);
return;
} else {
var folderList = files
.filter((item) => item.isDirectory())
.map((item) => item.name);
console.log(folderList);
};
});

I'm not aware of a way to ask readdir itself to give you a filtered list. You will need to filter them yourself, something like this:
let unwantedDirs = ['foo', 'bar'];
var folderList = files
.filter((item) =>
item.isDirectory() &&
!(unwantedDirs.includes(item.name)))

Related

creating multi sub directories in nodejs

I want to check if a directory not exist in my project, make two directories in my nodejs web api project. I use the following code and it works.
const myVar= req.body["specificId"];
const checkPath = path.join(__dirname , "../public/media/" + myVar);
console.log(checkPath);
if (!fs.existsSync(checkPath)) {
console.log("not exist!");
fs.mkdirSync(`${__dirname}../../public/media/`);
fs.mkdirSync(`${__dirname}../../public/media/${myVar}`);
fs.mkdirSync(`${__dirname}../../public/media/${myVar}/image`);
fs.mkdirSync(`${__dirname}../../public/media/${myVar}/video`);
}
else{
console.log("exist!");
}
but as you see I write 4 lines to do so. How may do it just by using something like the two last lines? I should mention that for the first run, just the specified 'public' folder exists and the other sub folders should be created if ${myVar} folder not existed.

How can I use Node.js fs to sort a set of folders according to their created date?

I'm building a node.js application in which I need to read all the folders in a parent folder and display their names in the order they were created on the page. Here is what I have so far:
function getMixFolders() {
const { readdirSync } = require('fs');
const folderInfo = readdirSync('./shahspace.com/music mixes/')
.filter(item => item.isDirectory() && item.name !== 'views');
return folderInfo.map(folder => folder.name);
}
As you can see, I haven't implemented sorting. This is because readdirSync doesn't return the information I need. The only things it returns are the name of the folder and something called the Symbol(type) (which seems to indicate whether its a folder or file).
Is there another method for getting more details about the folders I'm reading from the parent folder? Specifically the created date?
There is no super efficient way in nodejs to get a directory listing and get statistics on each item (such as createDate). Instead, you have to distill the listing down to the files/folders you're interested in and then call fs.statSync() (or one of the similar variants) on each one to get that info. Here's a working version that looks like it does what you want:
Get directory list using the {withFileTypes: true} option
Filter to just folders
Ignore any folders named "views"
Get createDate of each folder
Sort the result by that createDate in ascending order (oldest folders first)
This code can be run as it's own program to test:
const fs = require('fs');
const path = require('path');
const mixPath = './shahspace.com/music mixes/';
function getMixFolders() {
const folderInfo = fs.readdirSync(mixPath, { withFileTypes: true })
.filter(item => item.isDirectory() && item.name !== 'views')
.map(folder => {
const fullFolderPath = path.join(path.resolve(mixPath), folder.name);
const stats = fs.statSync(fullFolderPath);
return { path: fullFolderPath, ctimeMs: stats.ctimeMs }
}).sort((a, b) => {
return a.ctimeMs - b.ctimeMs;
});
return folderInfo;
}
let result = getMixFolders();
console.log(result);
If you wanted the final array to be only the folder names without the createDates you could add one more .map() to transform the final result.

Select all js files inside src folder (glob)

const glob = require('glob')
glob('src/**/**/**/**/**/**/**/***.js', {}, function(err, files) {})
istead of writing string like above src/**/**/**/**/**/**/**/***.js, I want to make it shorter and work similar way, but take any deep that can be inside of src folder. How can I achieve it ?

Gulp copying empty directories

In my gulp build I've made a task that runs after all compiling, uglifying and minification has occurred. This task simply copies everything from the src into the dest directory that hasn't been touched/processed by earlier tasks. The little issue I'm having is that this results in empty directories in the dest directory.
Is there a way to tell the gulp.src glob to only include files in the pattern matching (like providing the 'is_file' flag)?
Thanks.
Fixed it by adding a filter to the pipeline:
var es = require('event-stream');
var onlyDirs = function(es) {
return es.map(function(file, cb) {
if (file.stat.isFile()) {
return cb(null, file);
} else {
return cb();
}
});
};
// ...
var s = gulp.src(globs)
.pipe(onlyDirs(es))
.pipe(gulp.dest(folders.dest + '/' + module.folder));
// ...
I know I'm late to the party on this one, but for anyone else stumbling upon this question, there is another way to do this that seems pretty elegant in my eyes. I found it in this question
To exclude the empty folders I added { nodir: true } after the glob pattern.
Your general pattern could be such (using the variables from Nick's answer):
gulp.src(globs, { nodir: true })
.pipe(gulp.dest(folders.dest + '/' + module.folder));
Mine was as follows:
gulp.src(['src/**/*', '!src/scss/**/*.scss', '!src/js/**/*.js'], { nodir: true })
.pipe(gulp.dest('dev/'));
This selects all the files from the src directory that are not scss or js files, and does not copy any empty folders from those two directories either.

NodeJS - Copy and Rename all contents in existing directory recursively

I have a directory with folders and files within. I want to copy the entire directory with all its contents to a different location while renaming all the files to something more meaningful. I want to use nodejs to complete this series of operations. What is an easy way to do it, other than moving it one by one and renaming it one by one?
Thanks.
-- Thanks for the comment! So here is an example directory that I have in mind:
-MyFridge
- MyFood.txt
- MyApple.txt
- MyOrange.txt
- ...
- MyDrinks
- MySoda
- MyDietCoke.txt
- MyMilk.txt
- ...
- MyDesserts
- MyIce
...
I want to replace "My" with "Tom," for instance, and I also would like to rename "My" to Tom in all the text files. I am able to copy the directory to a different location using node-fs-extra, but I am having a hard time with renaming the file names.
Define your own tools
const fs = require('fs');
const path = require('path');
function renameFilesRecursive(dir, from, to) {
fs.readdirSync(dir).forEach(it => {
const itsPath = path.resolve(dir, it);
const itsStat = fs.statSync(itsPath);
if (itsPath.search(from) > -1) {
fs.renameSync(itsPath, itsPath.replace(from, to))
}
if (itsStat.isDirectory()) {
renameFilesRecursive(itsPath.replace(from, to), from, to)
}
})
}
Usage
const dir = path.resolve(__dirname, 'src/app');
renameFilesRecursive(dir, /^My/, 'Tom');
renameFilesRecursive(dir, /\.txt$/, '.class');
fs-jetpack has a pretty nice API to deal with problems like that...
const jetpack = require("fs-jetpack");
// Create two fs-jetpack contexts that point
// to source and destination directories.
const src = jetpack.cwd("path/to/source/folder");
const dst = jetpack.cwd("path/to/destination");
// List all files (recursively) in the source directory.
src.find().forEach(path => {
const content = src.read(path, "buffer");
// Transform the path however you need...
const transformedPath = path.replace("My", "Tom");
// Write the file content under new name in the destination directory.
dst.write(transformedPath, content);
});

Resources