210 lines
6.5 KiB
TypeScript
210 lines
6.5 KiB
TypeScript
import { readdirSync, statSync, writeFileSync, PathLike, existsSync, unlinkSync, mkdirSync, rmdirSync, createReadStream, accessSync, createWriteStream, constants, readFileSync, copyFileSync } from 'fs'
|
||
import { join } from 'path'
|
||
import { checkFileExistsAndCreateType } from './enum'
|
||
import { Error, error, Warn, warn } from './tip-style'
|
||
const pathList: Set<string> = new Set()
|
||
/**
|
||
* @name 读取目录下所有文件
|
||
* @export
|
||
* @param {string} entry 目录名称
|
||
*/
|
||
export function readDirPath(entry: string): Set<string> {
|
||
const dirInfo = readdirSync(entry);
|
||
for (let item of dirInfo) {
|
||
const location = join(entry, item);
|
||
const info = statSync(location);
|
||
if (info.isDirectory()) {
|
||
readDirPath(location);
|
||
} else {
|
||
pathList.add(location)
|
||
}
|
||
}
|
||
return pathList
|
||
}
|
||
|
||
/**
|
||
* @name 读取指定目录的文件(不进行深度遍历,只获取根目录)
|
||
* @export
|
||
* @param {*} entry
|
||
* @returns
|
||
*/
|
||
export function readDirGetFile(entry: string) {
|
||
const dirInfo = readdirSync(entry);
|
||
return dirInfo
|
||
}
|
||
|
||
/**
|
||
* @name 解析json文件(数组)
|
||
* @export
|
||
* @param {Array<string>} arr
|
||
* @returns
|
||
*/
|
||
export function parseJsonFiles(arr: Set<string>) {
|
||
const result = []
|
||
for (let item of arr) {
|
||
const data = parseJsonFile(item);
|
||
result.push(data)
|
||
}
|
||
return result
|
||
}
|
||
|
||
/**
|
||
* @name 解析单个文件json
|
||
* @export
|
||
* @param {PathLike} file
|
||
* @returns
|
||
*/
|
||
export function parseJsonFile(file: string) {
|
||
try {
|
||
const data = readFileSync(file, 'utf8');
|
||
return JSON.parse(data)
|
||
} catch (error) {
|
||
return
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @name 删除文件夹
|
||
* @export
|
||
* @param {string} entry
|
||
*/
|
||
export function deleteFolderRecursive(entry: string) {
|
||
let files = [];
|
||
// 判断给定的路径是否存在
|
||
if (existsSync(entry)) {
|
||
// 返回文件和子目录的数组
|
||
files = readdirSync(entry);
|
||
for (let file of files) {
|
||
const curPath = join(entry, file);
|
||
// fs.statSync同步读取文件夹文件,如果是文件夹,在重复触发函数
|
||
if (statSync(curPath).isDirectory()) { // recurse
|
||
deleteFolderRecursive(curPath);
|
||
// 是文件delete file
|
||
} else {
|
||
unlinkSync(curPath);
|
||
}
|
||
}
|
||
// 清除文件夹
|
||
rmdirSync(entry);
|
||
} else {
|
||
// console.log("文件夹不存在");
|
||
}
|
||
};
|
||
|
||
export function writeFile(path: string | PathLike, data: any) {
|
||
try {
|
||
writeFileSync(path, data)
|
||
} catch (err) {
|
||
Error(error(err))
|
||
Error(error('文件写入失败'))
|
||
}
|
||
}
|
||
|
||
export function readFile(
|
||
path: string | PathLike,
|
||
options?: { encoding?: null | undefined; flag?: string | undefined } | null
|
||
) {
|
||
try {
|
||
const data = readFileSync(path, options);
|
||
return data;
|
||
} catch (err) {
|
||
Error(error(err));
|
||
Error(error('文件读取失败'));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @name 拷贝文件夹
|
||
* @export
|
||
* @param {PathLike} currentDir
|
||
* @param {PathLike} targetDir
|
||
* @param {boolean} [overwrite=false] 是否覆盖已存在的文件
|
||
*/
|
||
export function copyFolder(currentDir: PathLike, targetDir: PathLike, overwrite: boolean = false) {
|
||
function handleFolder(currentDir: PathLike, targetDir: PathLike) {
|
||
const files = readdirSync(currentDir, {
|
||
withFileTypes: true
|
||
});
|
||
for (let file of files) {
|
||
const copyCurrentFileInfo = join(currentDir.toString(), file.name);
|
||
const copyTargetFileInfo = join(targetDir.toString(), file.name);
|
||
const readCurrentFile = existsSync(copyCurrentFileInfo);
|
||
const readTargetFile = existsSync(copyTargetFileInfo);
|
||
|
||
if (!readCurrentFile) {
|
||
console.error(`操作失败,待拷贝的源路径${copyCurrentFileInfo}不存在`);
|
||
throw new global.Error(`操作失败,待拷贝的源路径${copyCurrentFileInfo}不存在`);
|
||
}
|
||
else if (file.isFile() && readTargetFile && !overwrite) {
|
||
// console.warn(`目标文件${copyTargetFileInfo}已存在,跳过复制`);
|
||
continue;
|
||
}
|
||
else {
|
||
if (file.isFile()) {
|
||
// 使用同步复制确保文件完全写入
|
||
copyFileSync(copyCurrentFileInfo, copyTargetFileInfo);
|
||
// console.log(`复制文件: ${copyCurrentFileInfo} -> ${copyTargetFileInfo}`);
|
||
} else {
|
||
try {
|
||
accessSync(join(copyTargetFileInfo, '..'), constants.W_OK);
|
||
if (!existsSync(copyTargetFileInfo)) {
|
||
mkdirSync(copyTargetFileInfo);
|
||
}
|
||
// console.log(`创建文件夹: ${copyTargetFileInfo}`);
|
||
copyFolder(copyCurrentFileInfo, copyTargetFileInfo, overwrite);
|
||
} catch (error) {
|
||
console.error('权限不足', error);
|
||
throw error;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (existsSync(currentDir)) {
|
||
if (!existsSync(targetDir)) {
|
||
mkdirSync(targetDir);
|
||
// console.log(`创建目标文件夹: ${targetDir}`);
|
||
}
|
||
handleFolder(currentDir, targetDir);
|
||
} else {
|
||
console.error(`需要copy的文件夹不存在: ${currentDir}`);
|
||
throw new global.Error(`需要copy的文件夹不存在: ${currentDir}`);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @name 检测文件/文件夹是否存在
|
||
* @export
|
||
* @param {(PathLike | string)} path
|
||
* @returns
|
||
*/
|
||
export function checkFileExists(path: PathLike | string) {
|
||
return existsSync(path)
|
||
}
|
||
|
||
/**
|
||
* @name 检测文件/文件夹是否存在,不存在则创建
|
||
* @export
|
||
* @param {(PathLike | string)} path
|
||
* @param {*} [data]
|
||
* @param {checkFileExistsAndCreateType} [type=checkFileExistsAndCreateType.DIRECTORY]
|
||
*/
|
||
export function checkFileExistsAndCreate(path: PathLike | string, data?: any, type: checkFileExistsAndCreateType = checkFileExistsAndCreateType.DIRECTORY, overwrite?: boolean): void {
|
||
if (!checkFileExists(path) || overwrite) {
|
||
switch (type) {
|
||
case checkFileExistsAndCreateType.DIRECTORY:
|
||
mkdirSync(path)
|
||
break;
|
||
case checkFileExistsAndCreateType.FILE:
|
||
writeFile(path, data)
|
||
break;
|
||
default:
|
||
mkdirSync(path)
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
throw new global.Error(`${path} already exists!`);
|
||
}
|
||
} |