npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@kwooshung/files

v1.0.9

Published

A convenient and efficient library for file operations.

Downloads

16

Readme

@kwooshung/files

GitHub Release Date - Published_At GitHub last commit GitHub code size in bytes GitHub top language GitHub pull requests GitHub issues NPM Version Npm.js Downloads/Week Github CI/CD codecov Maintainability GitHub License Gitee Repo Github Stars

Why Develop It?

  • There are many excellent file operation libraries in the community, but they were not quite suitable for me.
  • Developing a new wheel doesn't mean the existing ones are bad; it's just about creating something more suited to my needs. I'm not creating a wheel for the sake of it, but rather to have a wheel that fits my requirements better.
  • This project also utilizes some excellent community projects, such as filehound.
  • I found this tool quite useful in my daily development. It's simple to use, which is why I decided to open-source it, hoping it could help others.

Why Use It?

  • It's composed entirely of functions, making it easy to use.
  • All functions related to path operations are normalized, so you don't have to worry about the format of the paths.
  • As much as possible, recursion is avoided, which helps when dealing with a large number of files and prevents potential stack overflows.
  • You can import as needed; it supports tree-shaking as an esm module, so you don't need to worry about the size after packaging.
  • There is also a commonjs (cjs) version available for those using the commonjs specification.
  • All functions in this project are based on fs/promises.
  • There is only 1 third-party dependency, hound, which relies on FileHound for file searching. If you don't need it, you can consider it as 0 third-party dependencies.

Install

npm

npm install @kwooshung/files

yarn

yarn add @kwooshung/files

pnpm

pnpm add @kwooshung/files

Functions

normalize Normalize Path

import { normalize } from '@kwooshung/files';

normalize('a/b/c'); // a/b/c
normalize('a//b/////c'); // a/b/c
normalize('a\\b\\c'); // a/b/c

exists Check if File or Directory Path Exists

import { exists } from '@kwooshung/files';

async () => {
  await exists('a/b/c'); // true
};

exists/not Check if File or Directory Path Does Not Exist

import { notExists } from '@kwooshung/files';

async () => {
  await notExists('a/b/c/aNotExists'); // true
};

isFile Check if Path is a File

import { isFile } from '@kwooshung/files';

async () => {
  await isFile('a/b/c/test.txt'); // true
};

isDir Check if Path is a Directory

import { isDir } from '@kwooshung/files';

async () => {
  await isDir('a/b/c'); // true
};

makeDir Create Directory

import { makeDir } from '@kwooshung/files';

async () => {
  await makeDir('a/b/c'); // Create a single directory
  await makeDir(['a/b/c/1', 'd/e/f/2']); // Create multiple directories
};

getDir Get Directory

import { getDir } from '@kwooshung/files';

async () => {
  await getDir('a/b/c'); // Returns an array of file or directory paths
};

read Read File

import { read } from '@kwooshung/files';

async () => {
  await read('a/b/c/test.txt'); // Returns the file content, the encoding is utf8 by default
  await read('a/b/c/test.txt', 'utf8'); // Returns the file content, specifying the encoding
};

write Write to File

  • The third parameter has a default value of { append: false, overwrite: true, encoding: 'utf8' }
  • If you are using ts, then the types of the third parameter append and overwrite are mutually exclusive, i.e.: when append is true, overwrite is false, and vice versa.
import { write } from '@kwooshung/files';

async () => {
  await write('a/b/c/test.txt', 'hello world'); // true

  await write('a/b/c/test.txt', 'hello world', {
    append: true, // Append
    overwrite: false, // Not Overwrite
    encoding: 'utf8' // Specify encoding
  }); // true


  await write('a/b/c/test.txt', 'hello world', {
    append: false, // Not Append
    overwrite: true // Overwrite, if the file does not exist, it will be created
    encoding: 'utf8' // Specify encoding
  }); // true

  await write('a/b/c/test.txt', 'hello world', {
    append: false, // Not Append
    overwrite: true // Overwrite, if the file does not exist, it will be created
  }); // true

  await write('a/b/c/test.txt', 'hello world', {
    encoding: 'binary' // Specify encoding
  }); // true
};

copy/file Copy File

As long as no exception is thrown, the copy is successful, even if the target file already exists.

import { copyFile } from '@kwooshung/files';

async () => {
  await copyFile('a/b/c/1.txt', 'd/e/f/2.txt'); // 表示覆盖目标文件
  await copyFile('a/b/c/1.txt', 'd/e/f/2.txt', false); // 即使目标文件已存在,虽然也不会覆盖,但是表示执行成功
};

copy/dir Copy Directory

  • If no exception is thrown, it means the copy was successful, even if the target directory already exists.
  • If the target directory exists, it will merge with the source. Identical files will be overwritten, but you can pass false as the third argument to prevent overwriting.
import { copyDir } from '@kwooshung/files';

async () => {
  await copyDir('a/b/c', 'd/e/f');
  await copyDir('a/b/c', 'd/e/f', false);
};

move/file Move File

Moving a file essentially copies the file and then deletes the source file. This approach ensures that if the move fails, the source file remains intact. It's a combination of copy/file and remove.

import { moveFile } from '@kwooshung/files';

async () => {
  await moveFile('a/b/c/1.txt', 'd/e/f/2.txt'); // 表示覆盖目标文件
  await moveFile('a/b/c/1.txt', 'd/e/f/2.txt', false); // 即使目标文件已存在,虽然也不会覆盖,但是表示执行成功
};

move/dir Move Directory

Moving a directory combines the functionalities of copy/dir and remove, thus it also follows the merging logic of copy/dir.

import { moveDir } from '@kwooshung/files';

async () => {
  await moveDir('a/b/c', 'd/e/f');
  await moveDir('a/b/c', 'd/e/f', false);
};

remove Delete File or Directory

import { remove } from '@kwooshung/files';

async () => {
  await remove('a/b/c'); // Delete a single file or directory
  await remove(['a/b/c/1', 'd/e/f/2']); // Delete multiple files or directories
};

remove/emptyDirs Delete Empty Directories at a Specified Path

This will delete all empty directories under the specified path, including the path itself.

import { removeEmptyDirs } from '@kwooshung/files';

async () => {
  await removeEmptyDirs('a/b/c'); // Delete a single file or directory
  await removeEmptyDirs(['a/b/c/1', 'd/e/f/2']); // Delete multiple files or directories
};

size Get the Size of a Specified Path or Multiple Paths

import { size } from '@kwooshung/files';

async () => {
  await size('a/b/c'); // [{path: 'a/b/c', size: 1200;}]
  await size(['a/b/c', 'd/e/f']); // [{path: 'a/b/c', size: 1200;}, {path: 'd/e/f', size: 2024;}]
};

size/human Convert a Number to a Human-Readable Size

import { sizeHuman } from '@kwooshung/files';

sizeHuman(1024); // {size: '1.25', unit: 'KB'}
sizeHuman(1024, 3); // {size: '1.234', unit: 'KB'}

size/unit Convert the Size of Specified Paths to Human-Readable Format

recommended to use with size

import { sizeUnit } from '@kwooshung/files';

async () => {
  await sizeUnit({path: 'a/b/c'; size: 1024;}); // [{path: 'a/b/c', size: '1200', unit: {size: '1.2', unit: 'KB'}}]
  await sizeUnit([{path: 'a/b/c'; size: 1024;}, {path: 'd/e/f'; size: 2024;}]); // [{path: 'a/b/c', size: '1200', unit: {size: '1.2', unit: 'KB'}}, {path: 'd/e/f', size: '2024', unit: {size: '2.02', unit: 'KB'}}]
};

hound FileHound

  • A wrapper for FileHound, used for creating a new instance of FileHound;
  • Also features the capabilities of FileHound.any, which means: multiple FileHound instances can be passed in, and the results will be merged;
import { hound } from '@kwooshung/files';

const fh1 = hound();
fh1
  .modified("< 2 days")
  .find()
  .each(console.log);

const fh2 = FileHound.create();
filehound
  .addFilter(customFilter)
  .find()
  .each(console.log);

hound(fh1, fh2);