Last active
December 2, 2025 11:05
-
-
Save Shariar-Hasan/d5835a48fd56696477d1e20a1aac10c6 to your computer and use it in GitHub Desktop.
A small script for syncing two folders to detect changes, additions, deletions of the src folder files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import fs from 'fs'; | |
| import path from 'path'; | |
| import { fileURLToPath } from 'url'; | |
| // ES module এ __dirname তৈরি | |
| const __filename = fileURLToPath(import.meta.url); | |
| const __dirname = path.dirname(__filename); | |
| // console colors | |
| const colors = { | |
| reset: "\x1b[0m", | |
| green: "\x1b[32m", | |
| yellow: "\x1b[33m", | |
| red: "\x1b[31m", | |
| blue: "\x1b[34m" | |
| }; | |
| // helper function: convert relative path to absolute | |
| function resolvePath(p) { | |
| return path.isAbsolute(p) ? p : path.resolve(__dirname, p); | |
| } | |
| /** | |
| * চেষ্টা করুন সবসময় ফোল্ডার পাথ এ ফরওয়ার্ড স্ল্যাশ (/) ব্যবহার করতে। | |
| * ব্যাকস্ল্যাশ (\) ব্যবহার করলে কিছু সময় সমস্যা হতে পারে, বিশেষ করে উইন্ডোজ এ। | |
| * উদাহরণ: 'E:/dev/src-path' instead of 'E:\dev\src-path' | |
| */ | |
| const paths = [ | |
| { | |
| src: "E:/DEV/school-management-api/src/entities", | |
| dest: "E:/DEV/hic-school-web-api/src/entities" | |
| }, | |
| { | |
| src: "E:/DEV/school-management-api/src/common/enums", | |
| dest: "E:/DEV/hic-school-web-api/src/common/enums" | |
| }, | |
| { | |
| src: "E:/DEV/school-management/src/models", | |
| dest: "E:/DEV/hic-school-web/src/models" | |
| }, | |
| ]; | |
| function syncFolder(src, dest) { | |
| if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true }); | |
| const srcFiles = fs.readdirSync(src); | |
| const destFiles = fs.existsSync(dest) ? fs.readdirSync(dest) : []; | |
| // check deleted files | |
| destFiles.forEach(file => { | |
| if (!srcFiles.includes(file)) { | |
| const destPath = path.join(dest, file); | |
| if (fs.statSync(destPath).isDirectory()) { | |
| fs.rmSync(destPath, { recursive: true, force: true }); | |
| } else { | |
| fs.unlinkSync(destPath); | |
| } | |
| console.log(`${colors.red}Deleted: ${file}${colors.reset}`); | |
| } | |
| }); | |
| // copy/update files | |
| srcFiles.forEach(file => { | |
| const srcPath = path.join(src, file); | |
| const destPath = path.join(dest, file); | |
| const srcStat = fs.statSync(srcPath); | |
| if (srcStat.isDirectory()) { | |
| syncFolder(srcPath, destPath); // recursive | |
| } else { | |
| if (!fs.existsSync(destPath)) { | |
| fs.copyFileSync(srcPath, destPath); | |
| console.log(`${colors.green}New file created: ${file}${colors.reset}`); | |
| } else { | |
| const srcContent = fs.readFileSync(srcPath, 'utf-8'); | |
| const destContent = fs.readFileSync(destPath, 'utf-8'); | |
| if (srcContent !== destContent) { | |
| fs.copyFileSync(srcPath, destPath); | |
| console.log(`${colors.yellow}Updated file: ${file}${colors.reset}`); | |
| } else { | |
| console.log(`${colors.blue}No change: ${file}${colors.reset}`); | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| // run sync | |
| paths.forEach(p => { | |
| const src = resolvePath(p.src); | |
| const dest = resolvePath(p.dest); | |
| console.log(`\nSyncing from ${src} → ${dest}`); | |
| syncFolder(src, dest); | |
| }); | |
| console.log(`${colors.green}\nAll sync completed!${colors.reset}`); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment