目录结构:
├── a.txt
├── b.txt
├── c.txt
├── files
└── index.js
index.js 文件:
const fs = require('fs').promises;
const path = require('path');
/**
* Move files by directory
* @param {String} directory
*/
async function moveFilesByDirectory(directory, inputExtname) {
const dirEntries = await fs.readdir(directory, { withFileTypes: true });
for (const dirEntry of dirEntries) {
if (dirEntry.isFile()) {
const { name: filename, ext } = path.parse(dirEntry.name);
const extname = ext.split('.').pop().toLocaleLowerCase();
if (extname === inputExtname) {
const dir = path.join(directory, filename)
await mkdir(dir);
const sourcePath = path.join(directory, dirEntry.name);
const destPath = path.join(dir, dirEntry.name);
console.log(sourcePath, destPath);
await mv(sourcePath, destPath);
}
}
}
}
moveFilesByDirectory('./files', 'txt');
/**
* Create a directory
* @param {String} dir
* @returns
*/
async function mkdir(dir) {
if (!(await exists(dir))) {
await fs.mkdir(dir);
}
return dir;
}
/**
* Check if the file exists
* @param {String} file
* @returns
*/
async function exists(file) {
try {
await fs.access(file);
return true;
} catch (err) {
return false;
}
}
/**
* Move
* @param {String} sourcePath
* @param {String} destPath
* @returns
*/
async function mv(sourcePath, destPath) {
try {
await fs.rename(sourcePath, destPath);
} catch (error) {
if (error.code === 'EXDEV') {
const readStream = fs.createReadStream(sourcePath);
const writeStream = fs.createWriteStream(destPath);
return new Promise((resolve, reject) => {
readStream.pipe(writeStream);
readStream.on('end', onClose);
readStream.on('error', onError);
async function onClose() {
await fsPromises.unlink(sourcePath);
resolve();
}
function onError(err) {
console.error(`File write failed with message: ${err.message}`);
writeStream.close();
reject(err)
}
})
}
throw error;
}
}