How to Delete Files Based on a Pattern with SHX and ShellJS

  • report
    Disclaimer
    Click for Disclaimer
    This Post is over a year old (first published about 4 years ago). As such, please keep in mind that some of the information may no longer be accurate, best practice, or a reflection of how I would approach the same thing today.
  • infoFull Post Details
    info_outlineClick for Full Post Details
    Date Posted:
    Jul. 23, 2020
    Last Updated:
    Aug. 11, 2020

Intro to SHX

One of my personal goals with NPM package development is to get better at cross-OS support; I don’t want to distribute code that only works in one specific environment. As part of my effort in working towards this, I discovered the shx CLI package, which is really mostly a wrapper around shelljs. Both of these tools let you write commands that use standard unix built-ins, like cat, but will work across any OS (Win / Mac / Linux).

For example, shx cat index.js

Using SHX to Delete Files Based on a Pattern

Problem:

If you are used to writing your commands without concern for portability, you might write a command to delete files based on a pattern like this:

# Delete all .md files in /dist
find dist -name '*.md' -delete

However, this command will fail with shx:

shx find dist -name '*.md' -delete

# ERROR: find: no such file or directory: -name

This is because the arguments to find are not currently supported by shx – you can find this tracked as issue #177.

Solution:

Since shx supports automatic glob expansion to standard commands, there is no reason why you can’t write the delete command as this:

shx rm 'dist/**/*.md'

Best Solution

There is a secondary problem here, which exists with many commands, which is that the command might exit with a non-zero code, preventing chained commands (ala &&) from running. This is especially problematic for NPM packages and the scripts section.

For example, if our package.json has this:

{
    "scripts": {
        "clean": "shx rm 'dist/**/*.md' && yarn build"
    }
}

… and there are no .md files inside dist, then the first part of the clean command will exit with:

error Command failed with exit code 1

… and yarn build will not execute.

There is any easy workaround though! Just use the & instead of the && operator, which lets the second command execute regardless of the success of the first.

You can also force the command to return exit 0, by piping and then returning true:

{
    "scripts": {
        "clean": "shx rm 'dist/**/*.md' || shx true && yarn build"
    }
}

Tip: You can also use shx --silent to suppress the displaying of the error message.

Leave a Reply

Your email address will not be published.