Automatically Move Files Using a Node.js Script

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.txt
2
/www/zk-prac/aa/bb/cc/gz-a.txt
3
/www/zk-prac/aa/bb/cc/dj-a.txt
4
/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:

Terminal window
1
pnpm 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:

1
import fs from "fs";
2
import path from "path";
3
import fse from "fs-extra";
4
import inquirer from "inquirer";
5
6
async function main() {
7
// Ask the user to input the source directory path
8
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
? true
16
: "Directory does not exist, please enter a valid path",
17
},
18
]);
19
20
// Ask the user to input the base target directory path
21
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
? true
29
: "Directory does not exist, please enter a valid path",
30
},
31
]);
32
33
// Ask the user to input the filename
34
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 directory
44
const files = fs.readdirSync(sourceDir);
45
46
// Find all target files with prefixes
47
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 path
57
const relativePath = path.relative(baseTargetDir, sourceDir);
58
59
// Find and exclude directories to be excluded from the base target directory
60
const targetPathParts = relativePath.split(path.sep);
61
targetPathParts.shift(); // Remove the first directory
62
63
// Calculate the actual target directory path
64
const subDir = targetPathParts.join(path.sep);
65
66
// Move files to each matching target directory
67
for (const file of matchedFiles) {
68
const prefix = file.split("-")[0];
69
const targetDirs = fs
70
.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
91
main().catch(console.error);

Usage Instructions

  1. When running the script, it will first ask the user for the source directory path.
  2. Then it will ask the user for the target basic directory path.
  3. The user will then input the file name to be moved (e.g., a.txt).
  4. 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.