0

I am new to shell script and recently wrote a script to open a new terminal window and run defined functions via osascript with "do shell script", but the result showed the command not found. My script is as below:

#!/bin/bash

hello() {
    echo "Hello World"
}

openNewWindowAndRun() {
    osascript -e "
        tell application \"Terminal\"
            activate        
            do script \"$1\"
        end tell
    "
}

openNewWindowAndRun hello

I have also tried to directly call the hello function in the openNewWindowAndRun but didn't get any luck:

#!/bin/bash

hello() {
    echo "Hello World"
}

openNewWindowAndRun() {
    osascript -e "
        tell application \"Terminal\"
            activate        
            do script \"hello\"
        end tell
    "
}

openNewWindowAndRun

When I ran the script, it opened the new window successfully but showed the error message: enter image description here

Does anyone know which part was missed here? Is it possible to pass a defined function as a parameter to osascript? If anyone can give me a hand, that would be great!

Andy Lu
  • 29
  • 1
  • 7
  • Functions are availbale in the process in which they are defined. You can export them to bash child processes by doing a `export -f hello`, but I don't know whether the `tell` command creates the bash as a child process. If it doesn't, the export wouldn't help you either. Why don't you make `hello` a program instead of a function? – user1934428 Feb 18 '22 at 09:34
  • I just tried the `export -f hello` but it didn't work, so I guess the `tell` command creates a new process. My intent was writing everything in one file so that it would be easy to share between team members, but thanks for sharing the idea making itself a program which could be a workaround – Andy Lu Feb 18 '22 at 11:29

2 Answers2

1

Your script will work fine if the function hello() is defined inside the .bashrc or .bash_profile or .zshrc (depends on which shell you are using).

The issue here is, when you are calling osascript to create a new terminal, the newly created terminal doesn't know about a function (or command) named hello.

So, you have to define it in such a way that every newly created terminal knows about that command. So, either you could put it in your .bashrc or you can create a shell script named hello in your $PATH and put the required code in that script.

j23
  • 3,139
  • 1
  • 6
  • 13
  • Thank for the explanation! It makes sense. Could you point me to how to create the `hello` script to my `$PATH`? I tried to convert the function to a script with `export -f hello` in `/usr/local/bin` and then ran my original script again, but it still showed the same error. I have checked `which hello` but it didn't show anything. Does that mean the exporting was incorrect and not working? – Andy Lu Feb 18 '22 at 11:48
  • 1
    You could create a file named `hello` in `/usr/local/bin` and then copy only the code ( `echo "Hello World"`) in that file. Or you can create a new directory and add its path. Consider you have a directory `scripts` in the home (ie. `~/scripts`). You add the directory to the path using `export PATH=~/scripts:$PATH` in `.zshrc` or `.bashrc`. Create a file `hello` in that folder and add only function code `echo "Hello World"`. After that set the permission for the file `hello` with `chmod +x hello`. Then do `source ~/.zshrc` (depends on your shell). After that everything will work. – j23 Feb 18 '22 at 12:50
  • 1
    It's working now! Thank you so much @j23 – Andy Lu Feb 18 '22 at 13:04
1

You can try following approach, which is not perfect, but it avoids changing initialization files like .bashrc or .zshrc:

#!/bin/bash

hello() {
    echo "Hello $@"
}

openNewWindowAndRun() {
    local  dirname="$(dirname  "$BASH_SOURCE")"
    local basename="$(basename "$BASH_SOURCE")"
    osascript -e "
        tell application \"Terminal\"
            activate        
            do script \"cd '$PWD'; clear; '$dirname/$basename' $*\"
        end tell
    " > /dev/null
}

${@:-openNewWindowAndRun hello World}

Run with: ./test.sh

Philippe
  • 20,025
  • 2
  • 23
  • 32
  • Hey @Philippe, thanks for the solution! It's working and interesting. I like the last line which is clever. I tried to remove `hello` and just ran `${@:-openNewWindowAndRun}` and it still working well. – Andy Lu Feb 19 '22 at 10:26
  • I've got one basic question: What is the `cd "$dir"` for? In my case, the result was `cd .`, so it changes the directory to the current directory? I'm confused about it. – Andy Lu Feb 19 '22 at 10:40
  • `abdir="$(cd "$dir"; pwd)"` is for the cases when you run the script from another directory, like `src/test.sh`. For `${@:-openNewWindowAndRun hello}`, I updated the script as I missed `$1` yesterday. – Philippe Feb 19 '22 at 10:57
  • 1
    Actually, we don't neet `abdir="$(cd "$dir"; pwd)"`. Updated – Philippe Feb 19 '22 at 11:10