mdawar.dev

A blog about programming, Web development, Open Source, Linux and DevOps.

Uninstall All NPM Global Packages

If you have a lot of npm packages installed globally and you want to remove them, here’s how you can do that without uninstalling them one by one:

bash
$npm -g rm $(node -e "console.log(Object.keys(JSON.parse(process.argv[1]).dependencies).filter(p => p !== 'npm').join(' '))" "$(npm ls -g --json --depth 0)")

You might need to use sudo if you don’t have the right permissions.

And below you can find the explanation of what this one line command is doing.

1. List the globally installed packages

This is how we can list the globally installed packages:

bash
$# -g: list the global packages
$# --depth 0: list only the installed packages without their dependencies
$npm ls -g --depth 0
/usr/lib
├── create-react-app@3.4.1
├── gatsby-cli@2.12.1
├── http-server@0.12.0
├── live-server@1.2.1
└── npm@6.14.4

We can also show a parseable output instead of the tree view using the -p flag:

bash
$npm ls -gp --depth 0
/usr/lib
/usr/lib/node_modules/create-react-app
/usr/lib/node_modules/gatsby-cli
/usr/lib/node_modules/http-server
/usr/lib/node_modules/live-server
/usr/lib/node_modules/npm

But we’re going to use the JSON output that you can get with the --json flag:

bash
$npm ls -g --json --depth 0
{
  "dependencies": {
    "create-react-app": {
      "version": "3.4.1",
      "from": "create-react-app",
      "resolved": "https://registry.npmjs.org/create-react-app/-/create-react-app-3.4.1.tgz"
    },
    "gatsby-cli": {
      "version": "2.12.1",
      "from": "gatsby-cli",
      "resolved": "https://registry.npmjs.org/gatsby-cli/-/gatsby-cli-2.12.1.tgz"
    },
    "http-server": {
      "version": "0.12.0",
      "from": "http-server",
      "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.0.tgz"
    },
    "live-server": {
      "version": "1.2.1",
      "from": "live-server",
      "resolved": "https://registry.npmjs.org/live-server/-/live-server-1.2.1.tgz"
    },
    "npm": {
      "version": "6.14.4"
    }
  }
}

2. Get the package names

Since we’re using Node we’re going to use JavaScript to parse this output to get the package names instead of using awk or grep or any other tool.

If you want, you can check these options on this StackOverflow question .

We can execute JavaScript using Node’s -e, --eval command line option:

bash
$node -e "console.log('Hey there')"
Hey there

And we can get the command line arguments using process.argv:

bash
$node -e "console.log(process.argv)" one two
[ '/usr/bin/node', 'one', 'two' ]

So we can pass the JSON output of the npm ls command as a command line argument:

bash
$node -e "console.log(process.argv)" "$(npm ls -g --json --depth 0)"
[
  '/usr/bin/node',
  '{\n' +
    '  "dependencies": {\n' +
    '    "create-react-app": {\n' +
    '      "version": "3.4.1",\n' +
    '      "from": "create-react-app",\n' +
    '      "resolved": "https://registry.npmjs.org/create-react-app/-/create-react-app-3.4.1.tgz"\n' +
    '    },\n' +
    '    "gatsby-cli": {\n' +
    '      "version": "2.12.1",\n' +
    '      "from": "gatsby-cli",\n' +
    '      "resolved": "https://registry.npmjs.org/gatsby-cli/-/gatsby-cli-2.12.1.tgz"\n' +
    '    },\n' +
    '    "http-server": {\n' +
    '      "version": "0.12.0",\n' +
    '      "from": "http-server",\n' +
    '      "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.0.tgz"\n' +
    '    },\n' +
    '    "live-server": {\n' +
    '      "version": "1.2.1",\n' +
    '      "from": "live-server",\n' +
    '      "resolved": "https://registry.npmjs.org/live-server/-/live-server-1.2.1.tgz"\n' +
    '    },\n' +
    '    "npm": {\n' +
    '      "version": "6.14.4"\n' +
    '    },\n' +
    '  }\n' +
    '}'
]

Finally we can parse process.argv[1] (The JSON string) and get the keys, and of course exclude npm:

bash
$node -e "
> // Parse the JSON string
> const json = JSON.parse(process.argv[1])
> // Get the keys (package names) and exclude 'npm'
> const pkgs = Object.keys(json.dependencies).filter(p => p !== 'npm')
> // Print to stdout the package names separated by spaces
> console.log(pkgs.join(' '))
> " "$(npm ls -g --json --depth 0)"
create-react-app gatsby-cli http-server live-server

This is the one line version:

bash
$node -e "console.log(Object.keys(JSON.parse(process.argv[1]).dependencies).filter(p => p !== 'npm').join(' '))" "$(npm ls -g --json --depth 0)"
create-react-app gatsby-cli http-server live-server

3. Uninstall the packages

Now we have a string of the package names separated by spaces, we can pass this string to npm uninstall :

bash
$# `rm` is an alias of `uninstall`
$npm -g rm $(node -e "console.log(Object.keys(JSON.parse(process.argv[1]).dependencies).filter(p => p !== 'npm').join(' '))" "$(npm ls -g --json --depth 0)")

And this is a verbose version of the above one liner:

bash
$# List of the installed packages as a JSON string
$JSON=$(npm ls -g --json --depth 0)
$# Script to parse the JSON and get the package names and exclude `npm`
$SCRIPT="console.log(Object.keys(JSON.parse(process.argv[1]).dependencies).filter(p => p !== 'npm').join(' '))"
$# Space separated string of the package names
$PKGS=$(node -e "$SCRIPT" "$JSON")
$# Uninstall the packages
$npm -g rm $PKGS