Need a "do shell script" which includes a pipe to run in background

I have a “do shell script” call which is to run in background and which involves piping output from one command to another. I also need the call to return the PiD. The first command outputs text while the second, a Perl script called “ts”, adds timestamps to each line then saves in a file. The call is in this form:

set output_file to "~/output.txt"
set shell_pid to do shell script " <command> 2>&1 | /usr/local/bin/ts &> " & output_file & " & echo $!"

where is a Python script that can take a long time to run. While is running, my AppleScript uses the PiD to monitor and report on progress.

But, I can’t get it to run in background. The call always waits for the to finish before continuing with the AppleScript. If I remove the pipe to “ts”, the call works properly by running the in background and continuing on with the AppleScript. But, then, I lose the timestamps.

Is there a way to run a “do shell script” call in background when it contains a “|” pipe ?

In fact, also, I can’t get the call to run in background if it contains a list using “;” separators e.g.:

set output_file to "~/output.txt"
set shell_pid to do shell script " sleep 5 ; ls > " & output_file & " & echo $!"

AppleScript always waits the 5 seconds or so before returning the PiD.

Dunno if this exactly matches your case but per TN2065 under ‘My script will produce output over a long time. How do I read the results as they come in?’:

https://developer.apple.com/library/archive/technotes/tn2065/_index.html#//apple_ref/doc/uid/DTS10003093-CH1-TNTAG5-MY_SCRIPT_WILL_PRODUCE_OUTPUT_OVER_A_LONG_TIME__HOW_DO_I_READ_THE_RESULTS_AS_THEY_COME_IN_

Well, yes, it is obvious that if you block the road with a cement block b[/b] and after the block you put a huge billboard b[/b] with the inscription “Welcome! We are so hospitable…”, the traveler will see this billboard, but will not be able to pass.

In your case, to solve the problem, the timestamp should be transferred not from the previous command, but by reading in an endless repeat the next timestamp from a file into which the first command writes all the time. Exit the repeat loop - as soon as the dies stop coming in.

That is, direct the timestamps output of your first command to some temporary file, and with the second command read timestamps from it.

do shell script "<command> &> " & tempFile_path & " &|/usr/local/bin/ts &> " & output_file & " & echo $!"

KniazidisR, many thanks. I’ll give that a try.

If you want the results as a variable check out Shane’s script

https://forum.latenightsw.com/t/applescriptobjc-and-do-shell-script/2069

I can’t get that suggestion to work. I got a syntax error until I deleted the “&” from before the “|”. This is my code:

set shell_pid to do shell script "ls &> ~/temp.txt | /usr/local/bin/ts &>  ~/output.txt & echo $!"

The code runs but the output.txt file is empty.

As a test, I ran the code in Terminal:

It worked in Terminal i.e. “zsh”, but when I ran it in sh, I got an empty output.txt file. I guess that means that sh handles pipes differently.

UPDATE: I’m looking at alternatives which don’t require piping e.g. ets.