tidyup
Version:
A simple CLI tool to organize files in a directory into categorized subfolders based on file types.
145 lines (141 loc) • 5.55 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
// src/index.ts
var import_commander = require("commander");
var import_fs = __toESM(require("fs"));
var import_path = __toESM(require("path"));
var import_util = require("util");
// package.json
var version = "0.0.7";
// src/index.ts
var readdir = (0, import_util.promisify)(import_fs.default.readdir);
var mkdir = (0, import_util.promisify)(import_fs.default.mkdir);
var rename = (0, import_util.promisify)(import_fs.default.rename);
var stat = (0, import_util.promisify)(import_fs.default.stat);
var FILE_TYPE_MAP = {
".png": "images-png",
".jpg": "images-jpg",
".jpeg": "images-jpeg",
".mp4": "videos-mp4",
".avi": "videos-avi",
".pdf": "documents-pdf"
};
var program = new import_commander.Command();
program.version(version).argument("[directory]", "Directory to tidy up", ".").description("Organize files in a directory based on their extensions").option("--ext", "Use the file extetions as folder names").option("--name", "Group files by starting name").action(async (inputDir, option) => {
const dirPath = import_path.default.resolve(inputDir);
try {
if (option.ext && option.name) {
console.error("Only one of --ext or --name can be used at a time");
process.exit(1);
}
const dirStat = await stat(dirPath);
if (!dirStat.isDirectory()) {
console.error(`The provided path is not a directory: ${dirPath}`);
process.exit(1);
}
await organizeFiles(dirPath, option);
} catch (error) {
console.error("An error occurred:", error.message);
process.exit(1);
}
});
program.parse(process.argv);
async function getFileTypes(dirPath) {
const files = await readdir(dirPath);
const fileTypes = {};
for (const file of files) {
const filePath = import_path.default.join(dirPath, file);
const fileStat = await stat(filePath);
if (fileStat.isFile()) {
const ext = import_path.default.extname(file).toLowerCase();
if (!fileTypes[ext]) {
fileTypes[ext] = [];
}
fileTypes[ext].push(filePath);
}
}
return fileTypes;
}
async function getFileNameGroups(dirPath) {
const files = await readdir(dirPath);
const nameGroups = {};
for (const file of files) {
const filePath = import_path.default.join(dirPath, file);
const fileStat = await stat(filePath);
if (fileStat.isFile()) {
const baseName = import_path.default.parse(file).name.slice(0, 10);
if (!nameGroups[baseName]) {
nameGroups[baseName] = [];
}
nameGroups[baseName].push(filePath);
}
}
return nameGroups;
}
async function organizeFiles(dirPath, options) {
let fileTypes;
if (options.name) {
fileTypes = await getFileNameGroups(dirPath);
} else {
fileTypes = await getFileTypes(dirPath);
}
const summary = [];
for (const [ext, filePaths] of Object.entries(fileTypes)) {
const newFolder = ext.split(".")[1];
const folderName = options.ext ? newFolder : FILE_TYPE_MAP[ext] || `others-${ext.replace(".", "")}`;
const folderPath = import_path.default.join(dirPath, folderName);
let folderCreated = false;
if (!import_fs.default.existsSync(folderPath)) {
await mkdir(folderPath);
folderCreated = true;
}
let filesAdded = 0;
for (const filePath of filePaths) {
const fileName = import_path.default.basename(filePath);
let newFilePath = import_path.default.join(folderPath, fileName);
if (import_fs.default.existsSync(newFilePath)) {
const fileBase = import_path.default.parse(fileName).name;
const fileExt = import_path.default.extname(fileName);
let counter = 1;
while (import_fs.default.existsSync(newFilePath)) {
const newFileName = `${fileBase}(${counter})${fileExt}`;
newFilePath = import_path.default.join(folderPath, newFileName);
counter++;
}
}
await rename(filePath, newFilePath);
filesAdded++;
}
summary.push({ folder: folderName, created: folderCreated, filesAdded });
}
const lastPath = dirPath.split("/");
const lastDir = lastPath[lastPath.length - 1];
console.log(`Organization Summary for '${lastDir}':`);
for (const { folder, created, filesAdded } of summary) {
console.log(`- Folder: ${folder}`);
console.log(` - ${created ? "Created" : "Already existed"}`);
console.log(` - Files added: ${filesAdded}`);
}
}