1

The following code forms a string (import statement), reads content from handler.js with awk, appends text after matched context "shell added import", then overwrite the file.

#!/bin/zsh
    
# setting path for project folders
HANDLER_PATH=${pwd}"workers/model/"
    
# just an import statement - being used as string
local IMPORT_TEXT=(import ${MAIN_FUNCTION} from "'./model/${MODEL_NAME}/${MODEL_NAME}'")
awk -v text=${IMPORT_TEXT} '1;/shell added import/{print text}' ${HANDLER_PATH}handler.js > ${HANDLER_PATH}handler.js_tmp && mv ${HANDLER_PATH}handler.js_tmp ${HANDLER_PATH}handler.js

Instead, it throws error [cannot read file]

Thing to note, it works in shell, but not from script.sh. Also, this similar code works on other files, as well as script. Adding permissions for the same:

Other file: -rw-r--r--  1 user  staff  9384
handler.js: -rw-r--r--  1 user  staff  7453

As per other thread i referred, it is "some permission issue if it works from terminal but not from script"

Any help is appreciated!

  • The script has a number of problems. I'd recommend adding a `set -x` command at the beginning so you can watch what's happening as it runs, then fixing the obvious problems. One that may not be obvious: the parentheses in `IMPORT_TEXT=(...)` don't act as any sort of quotes, they create an array, which I don't think is what you want. – Gordon Davisson Aug 12 '21 at 17:37
  • Since you've tagged your question with both bash and zsh I assume you don't care which shell you use so change your shebang to bash then copy/paste your shell script into http://shellcheck.net, fix the issues it tells you about plus the quoting (https://mywiki.wooledge.org/Quotes) and capitalization (https://stackoverflow.com/questions/673055/correct-bash-and-shell-script-variable-capitalization) problems and then if you still have a problem post a question about that corrected script. – Ed Morton Aug 12 '21 at 18:14
  • @GordonDavisson you are indeed correct with parenthesis. Bash isn't my everyday thing, so i read that () are needed for operators like + - % etc, here it serves as concatenation. If i don't wrap in () it takes space separated strings as commands. As for set -x, where exactly? The top of script or the command i wish to watch. Thank you – MorbidScroll Aug 12 '21 at 18:34
  • @EdMorton yes i have taken note of that, I even tried, but all it does is correct quotations. Otherwise the script is correct. It even works via terminal, yes it does in fact read and overwrite the file. But when executed from .sh file, it says it can't read the file. But like you said, I'll follow up on the references, thank you – MorbidScroll Aug 12 '21 at 18:37
  • Regarding `all it does is correct quotations` - that's not an "all", it's an extremely important works/fails change. Without the quotes your script will behave differently based on different environment settings, contents of the directory you run it from, input values, etc. – Ed Morton Aug 12 '21 at 18:38
  • You talk about bash in the comments (`Bash isn't my everyday thing...`) - you do know that your shebang `#!/bin/zsh` is invoking your script with zsh, not bash, right? The stuff you said after `i read that () are needed for ...` is completely wrong (for bash at least, and I doubt if zsh is different in this regard). `foo=(bar)` creates an array named `foo[]` with `foo[0]` containing `bar`, best I can tell you want `foo="bar"` instead. The stuff you think you need `(...)` for is a mix of what you need `((...))` for and `"..."` for. – Ed Morton Aug 12 '21 at 18:45
  • @EdMorton ooo that does make sense. yes i am aware my shebang is zsh and not bash. I was working with bash initially, but since mac has 3.2 a lot of solutions with newer bash implementations wouldn't work, so i gave zsh a try thinking they must have covered it. But then i couldn't use shellcheck.net. Hence, a lot of its and bits of various snippets lurk in my code. Not the best practice, but does help me cover my aim. For now – MorbidScroll Aug 12 '21 at 18:47
  • @EdMorton thank you. Quotation fix actually solved everything. – MorbidScroll Aug 12 '21 at 19:23
  • @MorbidScroll : Please make up your mind, whether to use bash or zsh. In particular with respect to quoting and to the usage of arrays, they are so different that it does not make much sense to discuss them in one question. – user1934428 Aug 13 '21 at 08:03
  • Yes, i have, I'm sticking to bash, especially because there's a debugger to it, unlike zsh. Also, yes i have noticed and understood the usage of array – MorbidScroll Aug 14 '21 at 04:25

2 Answers2

0

It sounds like this is what you're really trying to do (untested):

#!/usr/bin/env bash

# setting path for project folders
handler_path="$PWD/workers/model"
hdlr="$handler_path/handler.js"
tmp="${hdlr}_tmp"

# just an import statement - being used as string
import_text="import $MAIN_FUNCTION from \"'./model/$MODEL_NAME/$MODEL_NAME'\""

awk -v text="$import_text" '
    { print }
    /shell added import/ { print text }
' "$hdlr" > "$tmp" &&
mv -- "$tmp" "$hdlr"

I expect that'd work as-is in zsh too if you prefer that shell.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
0

What went wrong?

IMPORT_TEXT=(import ${MAIN_FUNCTION} from "'./model/${MODEL_NAME}/${MODEL_NAME}'")

... defines an array with multiple entries. Bash and zsh both support arrays, but do so differently. In bash, using the array like a normal variable retrieves the first entry (import in this case). In zsh, using the array like a normal variable retrieves all values as separate arguments.

Example:

$ bash -c 'a=(1 2 "a b" "*"); printf :%s:\\n $a'
:1:
$ zsh -c 'a=(1 2 "a b" "*"); printf :%s:\\n $a'
:1:
:2:
:a b:
:*:

It seems like your terminal used bash, resulting in the command

awk -v text=import '1;…' …

But when you ran the script directly, the shebang #!/bin/zsh caused it to run in zsh, resulting in the command

awk -v text=import "${MAIN_FUNCTION}" from "'./model/${MODEL_NAME}/${MODEL_NAME}'" '1;/…' …

Therefore, awk interpreted ${MAIN_FUNCTION} as the script to run, and everything after that as files. Since there was no file named from on your system, awk threw and error.

How to fix it?

See Ed Morton's answer

Socowi
  • 25,550
  • 3
  • 32
  • 54