javascript - Løkke gjennom filer i en mappe Node.JS
Jeg prøver å gå gjennom og hente filer i en katalog, men jeg har problemer med å implementere det. Hvordan kan man hente flere filer og deretter flytte dem til en annen mappe?
var dirname = 'C:/FolderwithFiles';
console.log("Going to get file info!");
fs.stat(dirname, function (err, stats) {
if (err) {
return console.error(err);
}
console.log(stats);
console.log("Got file info successfully!");
// Check file type
console.log("isFile ? " + stats.isFile());
console.log("isDirectory ? " + stats.isDirectory());
});
Svar #1
Eldre svar med tilbakeringinger
Du vil bruke fs.readdir-funksjonen for å få innholdet i katalogen og fs.rename-funksjonen for faktisk å utføre omdøpingen. Begge disse funksjonene har synkrone versjoner hvis du trenger å vente på dem før du kjører koden etterpå.
Jeg skrev et raskt skript som gjør det du beskrev.
var fs = require('fs');
var path = require('path');
// In newer Node.js versions where process is already global this isn't necessary.
var process = require("process");
var moveFrom = "/home/mike/dev/node/sonar/moveme";
var moveTo = "/home/mike/dev/node/sonar/tome"
// Loop through all the files in the temp directory
fs.readdir(moveFrom, function (err, files) {
if (err) {
console.error("Could not list the directory.", err);
process.exit(1);
}
files.forEach(function (file, index) {
// Make one pass and make the file complete
var fromPath = path.join(moveFrom, file);
var toPath = path.join(moveTo, file);
fs.stat(fromPath, function (error, stat) {
if (error) {
console.error("Error stating file.", error);
return;
}
if (stat.isFile())
console.log("'%s' is a file.", fromPath);
else if (stat.isDirectory())
console.log("'%s' is a directory.", fromPath);
fs.rename(fromPath, toPath, function (error) {
if (error) {
console.error("File moving error.", error);
} else {
console.log("Moved file '%s' to '%s'.", fromPath, toPath);
}
});
});
});
});
Testet på maskinen min lokalt.
node testme.js
'/home/mike/dev/node/sonar/moveme/hello' is a file.
'/home/mike/dev/node/sonar/moveme/test' is a directory.
'/home/mike/dev/node/sonar/moveme/test2' is a directory.
'/home/mike/dev/node/sonar/moveme/test23' is a directory.
'/home/mike/dev/node/sonar/moveme/test234' is a directory.
Moved file '/home/mike/dev/node/sonar/moveme/hello' to '/home/mike/dev/node/sonar/tome/hello'.
Moved file '/home/mike/dev/node/sonar/moveme/test' to '/home/mike/dev/node/sonar/tome/test'.
Moved file '/home/mike/dev/node/sonar/moveme/test2' to '/home/mike/dev/node/sonar/tome/test2'.
Moved file '/home/mike/dev/node/sonar/moveme/test23' to '/home/mike/dev/node/sonar/tome/test23'.
Moved file '/home/mike/dev/node/sonar/moveme/test234' to '/home/mike/dev/node/sonar/tome/test234'.
Oppdatering: fs.promises-funksjoner med async/await
Inspirert av ma11hew28s svar (vist her), her er det samme som ovenfor, men med de asynkrone funksjonene i fs.promises. Som påpekt av ma11hew28, kan dette ha minnebegrensninger sammenlignet med fs.promises.opendir lagt til i v12.12.0.
Rask kode nedenfor.
//jshint esversion:8
//jshint node:true
const fs = require( 'fs' );
const path = require( 'path' );
const moveFrom = "/tmp/movefrom";
const moveTo = "/tmp/moveto";
// Make an async function that gets executed immediately
(async ()=>{
// Our starting point
try {
// Get the files as an array
const files = await fs.promises.readdir( moveFrom );
// Loop them all with the new for...of
for( const file of files ) {
// Get the full paths
const fromPath = path.join( moveFrom, file );
const toPath = path.join( moveTo, file );
// Stat the file to see if we have a file or dir
const stat = await fs.promises.stat( fromPath );
if( stat.isFile() )
console.log( "'%s' is a file.", fromPath );
else if( stat.isDirectory() )
console.log( "'%s' is a directory.", fromPath );
// Now move async
await fs.promises.rename( fromPath, toPath );
// Log because we're crazy
console.log( "Moved '%s'->'%s'", fromPath, toPath );
} // End for...of
}
catch( e ) {
// Catch anything bad that happens
console.error( "We've thrown! Whoops!", e );
}
})(); // Wrap in parenthesis and call now
Svar #2
fs.readdir(path[, options], callback) (som Mikey A. Leonetti brukte i sitt svar) og dets varianter (fsPromises.readdir(path[, options]) og fs.readdirSync(path[, options])) leser hver alle oppføringene i en katalog til minnet på en gang. Det er bra for de fleste tilfeller, men hvis katalogen har veldig mange oppføringer og/eller du ønsker å redusere applikasjonens minnebruk, kan du i stedet iterere over katalogens oppføringer én om gangen.
Asynkront
Mapper er asynkrone itererbare, så du kan gjøre noe som dette:
const fs = require('fs')
async function ls(path) {
const dir = await fs.promises.opendir(path)
for await (const dirent of dir) {
console.log(dirent.name)
}
}
ls('.').catch(console.error)
Eller, du kan bruke dir.read() og/eller dir.read(callback) direkte.
Synkront
Mapper er ikke synkroniserbare iterable, men du kan bruke dir.readSync() direkte. For eksempel:
const fs = require('fs')
const dir = fs.opendirSync('.')
let dirent
while ((dirent = dir.readSync()) !== null) {
console.log(dirent.name)
}
dir.closeSync()
Eller, du kan gjøre kataloger synkroniserbare itererbare. For eksempel:
const fs = require('fs')
function makeDirectoriesSyncIterable() {
const p = fs.Dir.prototype
if (p.hasOwnProperty(Symbol.iterator)) { return }
const entriesSync = function* () {
try {
let dirent
while ((dirent = this.readSync()) !== null) { yield dirent }
} finally { this.closeSync() }
}
if (!p.hasOwnProperty(entriesSync)) { p.entriesSync = entriesSync }
Object.defineProperty(p, Symbol.iterator, {
configurable: true,
enumerable: false,
value: entriesSync,
writable: true
})
}
makeDirectoriesSyncIterable()
Og så kunne du gjøre noe slik:
const dir = fs.opendirSync('.')
for (const dirent of dir) {
console.log(dirent.name)
}
Merk: "I travle prosesser, bruk de asynkrone versjonene av disse kallene. De synkrone versjonene vil blokkere hele prosessen til de fullføres, og stoppe alle forbindelser."
Referanser:
- Node.js-dokumentasjon: Filssystem:
Klasse fs.Dir - Node.js kildekode:
fs.Dir - GitHub: nodejs/node: Problemer: strømming/iterativ fs.readdir #583
