Extending on the other answer and use the %run magic command1, it's possible to do this (which works for multiple-line scripts):
$ jupyter console --simple-prompt --existing kernel-8987.json <<< '%run script.py'
or (on Windows where <<< doesn't work)
> echo %run script.py | jupyter console --simple-prompt --existing kernel-8987.json
Unfortunately, this method still prints some redundant prompt (In[1]:) on the console.
Alternatively, using Python API: (create a script to execute this Python code) (on my machine, this method is much faster)
from jupyter_client.manager import KernelManager
manager=KernelManager(connection_file="full path to connection file.json")
manager.load_connection_file()
manager.client().execute("commands to execute")
The commands to execute might span multiple lines, or have the form %run file.py.
There's also silent=True, store_history=False as parameters to execute().
The full path to the connection file can be found as
Path(jupyter_core.paths.jupyter_runtime_dir()) / "kernel-8987.json", or 
jupyter_client.connect.find_connection_file("kernel-8987.json") (find file with specific name), or 
jupyter_client.connect.find_connection_file() (find the latest file) 
See also jupyter-client documentation.
Disclaimer: Some of the code are taken from jupyter-vim plugin, and manager.load_connection_file and connect.find_connection_file appears to be undocumented.
1: As mentioned in the documentation, the file is executed in a new namespace unless you use -i.