Automatically Move Files Using a Node.js Script
- 559Words
- 3Minutes
- 19 Jul, 2024
Recently, I encountered a requirement to move certain files from a specified directory to other directories. Specifically, suppose the user needs to move a file named a.txt
. We need to find other files in the current directory that include the prefix a.txt
, such as gz-a.txt
, dj-a.txt
, ny-a.txt
, etc., and then move these files to the corresponding target directories, renaming them to a.txt
. After moving, the original files in the source directory should be deleted.
Example Directory Structure
The source directory (user-provided source directory path, e.g., /www/zk-prac/aa/bb/cc
) might contain the following files:
1/www/zk-prac/aa/bb/cc/a.txt2/www/zk-prac/aa/bb/cc/gz-a.txt3/www/zk-prac/aa/bb/cc/dj-a.txt4/www/zk-prac/aa/bb/cc/ny-a.txt
The basic target directory (user-provided target basic directory path, e.g., /www/
) has the following structure:
1/www/gz-prac/aa/bb/cc/2/www/dj-prac/aa/bb/cc/3/www/ny-prac/aa/bb/cc/
In this example, the script needs to move /www/zk-prac/aa/bb/cc/gz-a.txt
to /www/gz-prac/aa/bb/cc/a.txt
, /www/zk-prac/aa/bb/cc/dj-a.txt
to /www/dj-prac/aa/bb/cc/a.txt
, and /www/zk-prac/aa/bb/cc/ny-a.txt
to /www/ny-prac/aa/bb/cc/a.txt
while deleting the source files.
Script Implementation
Install two dependencies:
1pnpm add inquirer fs-extra
Since ES Module is being used, you need to add the following declaration to package.json
:
1"type": "module",
Here is the Node.js script to achieve this requirement:
1import fs from "fs";2import path from "path";3import fse from "fs-extra";4import inquirer from "inquirer";5
6async function main() {7 // Ask the user to input the source directory path8 const { sourceDir } = await inquirer.prompt([9 {10 type: "input",11 name: "sourceDir",12 message: "Please enter the source directory path:",13 validate: (input) =>14 fs.existsSync(input)15 ? true16 : "Directory does not exist, please enter a valid path",17 },18 ]);19
20 // Ask the user to input the base target directory path21 const { baseTargetDir } = await inquirer.prompt([22 {23 type: "input",24 name: "baseTargetDir",25 message: "Please enter the base target directory path:",26 validate: (input) =>27 fs.existsSync(input)28 ? true29 : "Directory does not exist, please enter a valid path",30 },31 ]);32
33 // Ask the user to input the filename34 const { targetFileName } = await inquirer.prompt([35 {36 type: "input",37 name: "targetFileName",38 message: "Please enter the filename to move (e.g., a.txt):",39 validate: (input) => (input ? true : "Filename cannot be empty"),40 },41 ]);42
43 // Get all files in the source directory44 const files = fs.readdirSync(sourceDir);45
46 // Find all target files with prefixes47 const matchedFiles = files.filter(48 (file) => file.endsWith(targetFileName) && file !== targetFileName,49 );50
51 if (matchedFiles.length === 0) {52 console.log("No matching prefix files found.");53 return;54 }55
56 // Calculate the relative path57 const relativePath = path.relative(baseTargetDir, sourceDir);58
59 // Find and exclude directories to be excluded from the base target directory60 const targetPathParts = relativePath.split(path.sep);61 targetPathParts.shift(); // Remove the first directory62
63 // Calculate the actual target directory path64 const subDir = targetPathParts.join(path.sep);65
66 // Move files to each matching target directory67 for (const file of matchedFiles) {68 const prefix = file.split("-")[0];69 const targetDirs = fs70 .readdirSync(baseTargetDir)71 .filter((dir) => dir.startsWith(prefix));72
73 for (const targetDir of targetDirs) {74 const targetPath = path.join(baseTargetDir, targetDir, subDir);75 const sourceFilePath = path.join(sourceDir, file);76 const targetFilePath = path.join(targetPath, targetFileName);77
78 try {79 await fse.ensureDir(targetPath);80 await fse.copy(sourceFilePath, targetFilePath);81 console.log(`Moved ${file} to ${targetFilePath}`);82 await fse.remove(sourceFilePath);83 console.log(`Deleted source file ${sourceFilePath}`);84 } catch (err) {85 console.error(`Error moving or deleting file: ${err}`);86 }87 }88 }89}90
91main().catch(console.error);
Usage Instructions
- When running the script, it will first ask the user for the source directory path.
- Then it will ask the user for the target basic directory path.
- The user will then input the file name to be moved (e.g.,
a.txt
). - The script will find all target files with the prefix in the source directory and move them to the corresponding target directories, renaming the files to the user-specified file name and deleting the source files.