0

I'm trying to write a very simple bash function that uses a one-line node script to read the value of a key from a JSON file. Here's the current contents of utils.bash:

#!/bin/bash

project_name() {
    echo $(node -e "require('../package.json').name;")
}

Yes, I know there are tools around that allow me to access JSON data more directly, but all of the dev team already has node, so it's an existing dependency rather than a new one.

I've made the file executable, but when I source scripts/utils.bash and then attempt to reference the function (from the command line) as so:

PROJECT_NAME=project_name

the output is simply the line I typed. When I try to execute simply project_name, I get a node error:

Error: Cannot find module '../package.json'

The utils.bash script is in the project's scripts folder, and the package.json file is in the parent folder. I'm executing this from the parent folder (although I'd prefer it not matter). I've tried importing './package.json', but that also gives me an error.

The end result I want is to be able to reference the value of the name key in project.json through multiple bash scripts.

How can I do this?

1 Answer 1

2

Well, the problem with PROJECT_NAME=project_name is it should be PROJECT_NAME="$(project_name)". The quotes in that case are not necessary as it's in an assignment to a scalar variable, but are a good habit to get into as in many other contexts (including your echo $(...)), omitting quotes implies splitting the result on $IFS characters and perform globbing on the resulting words which you do not want here.

The function has the same working directory as where it's run from, and you said you ran it in the parent of scripts. So the function is looking for ./../package.json not ./scripts/../package.json.

So you'll likely want to use ./package.json (not package.json as when the path has no /, node looks in a default search path instead of the current working directory) and figure out why it's giving you an error.

You'll also need node to output that value with console.log(), and remove that echo with $(...) which makes no sense (especially with that $(...) unquoted as seen above). So:

package_name() {
  node -e "console.log(require('./package.json').name)"
}
PACKAGE_NAME="$(package_name)" || handle error from node if any
2
  • Just to clarify for anyone else who might be wondering, the echo in the script needs to be echo $(node -e "console.log(require('./package.json').name);").
    – Chuck
    Commented Oct 28, 2023 at 21:44
  • That echo isn't needed at all: shellcheck.net/wiki/SC2005 Commented Oct 29, 2023 at 1:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .