bashapplescriptshprocess-substitution

Is it possible to use command substitution in an applescript call to `do shell script`?


I have an automator service that I was updating to handle a series of input files in combination (instead of serially, like it currently does). It does a bunch of stuff, but in one component of it, I need to process the contents of N files and hand the processing of the output of each file off to a single paste command to combine it all and further process the combo. On the command line, I would do it with process substitution, e.g.:

paste <(commands processing file 1) <(commands processing file 2) ... | other processing commands

But if I do this from inside an applescript, like this:

set output to (do shell script "paste <(commands processing file 1) <(commands processing file 2) ... | other processing commands")

I get an error from applescript:

The action “Run AppleScript” encountered an error: “Finder got an error: sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `paste <(commands processing file 1) <(commands processing file 2) ... | other processing commands'”

I learned that this is because sh doesn't do the fancy stuff that bash does, e.g. process substitution.

I know I could just write temporary files to accomplish my goal, but I'd rather not have to if there's a way around it.

I tried getting around this by using bash -s:

set output to (do shell script "bash -s <<'EOF'" & return & "paste <(commands processing file 1) <(commands processing file 2) | other processing commands" & return & "EOF")

But that yields the same error.

Any idea how to accomplish this without having to write temporary files?

UPDATE: I realized that I pared the problem down too much. There is a bit more to it. The series of commands I am using (including the paste command mentioned already), includes one-liner code that contains variables and single-quotes, so the solution would need have to prevent shell interpolation of variables and not interfere with single-quotes. I will update the toy example below to include those details.


Toy example (applescript):

file 1:

this is the first test

file 2:

this is the second test

applescript:

set file1 to "~/file1.txt"
set file2 to "~/file2.txt"
set output to (do shell script "paste <(head " & file1 & " | perl -ne 'chomp;print(substr($_,0,4),qq(\\n))') <(head " & file2 & " | perl -ne 'chomp;print(substr($_,-4),qq(\\n))')"
display dialog output

Expected output:

this    test

Note, there are other variables and another command (awk) using single quotes.


Solution

  • Oh my gosh! Right after I posted this, I realized that all I needed to do was escape the parens. I was on the right track with bash -s! I think writing out the question was just the process I had to go through to realize the answer!

    set output to (do shell script "bash -s <<'EOF'" & return & "paste \\<\\(commands processing file 1\\) \\<\\(commands processing file 2\\) | other processing commands" & return & "EOF")
    

    I can't believe I didn't see it before posting the question!