5

My objective is to only install this npm package if it's not already available. This continues to to execute even when I've installed the module globally.

if [ npm list -g widdershins &> /dev/null ] || [ ! -d node_modules ]; then
    npm install widdershins --no-shrinkwrap
fi

How can I adjust this to detect when it's installed globally?

Ben
  • 60,438
  • 111
  • 314
  • 488
  • 1
    The first clause has an exit status of 0 ("true") if the module is already installed, isn't that the opposite of what you want? – Benjamin W. May 22 '18 at 20:02

3 Answers3

19

if you want a one liner:

Local

npm list | grep widdershins || npm install widdershins --no-shrinkwrap

Global:

npm list -g | grep widdershins || npm install -g widdershins --no-shrinkwrap
OZZIE
  • 6,609
  • 7
  • 55
  • 59
9
package='widdershins'
if [ `npm list -g | grep -c $package` -eq 0 ]; then
    npm install $package --no-shrinkwrap
fi

alternative including the directory check:

package='widdershins'
if [ `npm list -g | grep -c $package` -eq 0 -o ! -d node_module ]; then
    npm install $package --no-shrinkwrap
fi

Explaination:

  • npm list -g lists all installed packages
  • grep -c $package prints a count of lines containing $package (which is substituted to 'widdershins' in our case)
  • -eq is an equals check, e.g. $a -eq $b returns true if $a is equal to $b, and false otherwise.
  • -d checks if the given argument is a directory (returns true if it is)
  • ! is the negation operator, in our case is negates the -d result
  • -o is the logical or operator

To sum it up:

  • First code: if the $package is installed, then the -eq result is false and this causes the if statement to be false. If $package is not installed, then the -eq result is true (and the if statement is also true).
  • Second code: in addition to description of first code, if node_module is a directory, then the if statement is false. If node_module is not a directory then the if statement is true. And this is independend from the -eq result because of the logical or connection.

This could also help you.

Rene Knop
  • 1,788
  • 3
  • 15
  • 27
  • This doesn't seem to quite work. `widdershins@3.4.0` is in the output of `npm list -g` but it's still trying to install – Ben May 23 '18 at 13:07
  • What does `-eq 0 -o` do? – Ben May 23 '18 at 13:27
  • `-eq` is an equals check. It returns true if the left operator is equal to the right operator. `grep -c $package` counts all lines containing $package (in this case all lines containing the string 'widdershins', and this is also true for 'widdershins@3.4.0'). This means: if the package widdershins is installed, then ``npm list -g | grep -c $package`` returns 1, and this is not equal to 0 (1 -eq 0 is false). The `-o` is the logical `or` operator. It connects the -eq result with the directory check result (`! -d node_module`, which is true, if node_modules is not a directory). Hope this helps. – Rene Knop May 23 '18 at 14:07
  • I think what's messing this up is that it's putting this on line 1, `npm ERR! peer dep missing: mkdirp@>=0.5.0, required by mkdirp-promise@1.1.0` then the count actually shows up on line 2 – Ben May 23 '18 at 14:16
  • Ok, if i understand this correctly, then i think you have another problem: a problem based on a missing dependency. Maybe on this post you'll find help with this: https://stackoverflow.com/questions/41275301/how-to-fix-npm-missing-peer-dependency – Rene Knop May 23 '18 at 14:35
1

This worked for me:

package_name='widdershins'
if [[ "$(npm list -g $package_name)" =~ "empty" ]]; then
    echo "Installing $package_name ..."
    npm install -g $package_name
else
    echo "$package_name is already installed"
fi

npm list -g package-name returns empty when is not installed, so with that condition you can check if it contains the string empty

helvete
  • 2,455
  • 13
  • 33
  • 37
codiwan
  • 61
  • 1
  • 3