Jump to content
Misha

selection in macos + keyword

Recommended Posts

Hi guys, I have a workflow in which I use the (selection in macOS) as the "query" in a bash script (it runs an OCR on the selected file). To do this, I use the "argument: Selection in macOS" of the "hotkey", but I would rather use a keyword (rather than a hotkey) to run the script (so that I can for instance more easily run the OCR_english and OCR_dutch versions of the script). Is this possible?

Share this post


Link to post
1 hour ago, Misha said:

Is this possible?

 

Not easily, no. If you're using a keyword, then the active application is Alfred (as you're entering your query into it), which isn't where you want to get your selection from.

 

You can work around it in a workflow by attaching your keyword to a Run Script action that simulates a ⌘C keypress and then uses pbpaste to grab the contents of the pasteboard.

 

That doesn't work quite a smoothly as using Alfred's built-in feature, however. Your best bet is therefore to use a Hotkey.

 

Share this post


Link to post

Hi @Misha, I did a small workflow as example to show you multiple ways of doing it (using a: File action, a Hotkey or a Keyword). This way you can use the way you find it best for your use case. Myself I would use the file action since you want to work with files and this is made for that... but any method should works great

 

Here is the workflow: https://nofile.io/f/O7scHb0o3rm/File+Selection+&+OCR_Keywords.alfredworkflow

 

Hope this helps!

 

 

Edited by GuiB

Share this post


Link to post

Thanks a lot guys, these are great suggestions. I decided for now to just use a file action, which is working fine. (Thanks for the great example-workflow @GuiB!)

Edited by Misha

Share this post


Link to post

@GuiB Thanks for posting the following workflow:

 

On 7/19/2017 at 9:43 PM, GuiB said:

 

This was extremely helpful! Similar to @Misha I was trying to get a keyword to operate like a hotkey - which passes the selected items from Finder - and your workflow helped tremendously.

 

That said, even after following the example, I was not able to get my workflow working with more than one file at a time (i.e., when more than one file is selected in Finder and you want to run the script on each of the files). It just runs for one of the files that are selected. Is there anything special that needs to be done to your example workflow when working with multiple files?

 

For example, I'd like to send a few files to an automator script. When I run the script from a file action on one or more files, I use the following bash script (with input as query):

files="{query}"
IFS="    "
set $files
for file in $files
do
    automator -i "$file" "/Users/NAME/Library/Services/NAME.workflow"
done

It works great, but I was hoping to run the script from a keyword, too. 

 

To accomplish this, I tried adapting your workflow. First, I changed the osascript step to the following (adding the first line😞

set my text item delimiters to tab

tell application "Finder" to return POSIX path of (selection as text)

Then, I changed the bash script step to the following (with input as argument😞

query=$1

IFS="	"
set $1

for file in $1
do
	automator -i "$1" "/Users/NAME/Library/Services/NAME.workflow"
done

However, it only ever works on one of the files that are selected in Finder. From what I can tell after digging around, it looks like the number $1 is telling the bash script to only run on the first file. Is this correct?  If so, how should your model be adapted to run for each file?

 

Oddly enough, if I attach the osascript step (above - second snippet of code provided) to the original file action's bash script (above - first snippet of code provided), it does the same thing when run from a keyword. As a result, I think the problem is with the osascript step (above - second snippet of code provided)? I added the "set my text item delimiters to tab" to your script, but perhaps it needs a few more changes (i.e., so that it copies the names of each file in the same manner that a hotkey would using the macOS selection option)?

 

Thanks for your help (and for posting this example workflow)!!

Share this post


Link to post

@Jasondm007 I've updated the script for you to work with a multi selection. In short, you were not too far from having it. It's mainly your loop over your file list. I have changed it to:

 

# Change IFS to TAB and expand into an array
IFS=$'\t' filesListArr=($@)

# Loop over the file list array
for file in "${filesListArr[@]}"
do
    # Your script to be run
    automator -i "$file" "/Users/NAME/Library/Services/NAME.workflow"
done

 

Here is the updated workflow:

https://nofile.io/f/8ugP4mSgOMu/File+Multi+Selection+&+OCR_Keywords.alfredworkflow

 

Also, I've edited every action to work with a multi selection, so you get an example with a File Action, a Hotkey and a Keyword action

Edited by GuiB

Share this post


Link to post

@GuiB Thanks for getting back to me, and for taking a look at this. I really appreciate it.

 

By chance, does the osascript need to be updated? I'm still having the same issue. 

 

When troubleshooting - to see what the file list looks like - I attached that step to a clipboard, and the files look a little different (one of the files looks correct, but the other has "Macintosh HD" specification). Is it possible that this is the step with the problem?

 

Thanks again for all of your help!

Share this post


Link to post

Yes, if you look inside the AppleScript node, I've set it as you did. However, now that you mention that, you're right that the first path uses /Users/ and the other /Macintosh HD/. I tried another way before switching to yours since I didn't test it first and then when I tested your I thought everything was fine. But my other version was to loop over the Finder selection to build a string delimited by TAB. I've tried again my version and with it I get all "/Users/" kind of paths

 

Here is my modified AppleScript code:

tell application "Finder" to set theSelection to selection as alias list
set theFileList to ""
repeat with i from 1 to count of theSelection
	set theFileList to theFileList & "\t" & POSIX path of item i of theSelection as string
end repeat

return theFileList

 

And here is the new Workflow if you want to see it:

https://nofile.io/f/scHz3m70RpG/File+Multi+Selection+&+OCR_Keywords.alfredworkflow

 

Let me know how it goes!

 

Share this post


Link to post

@Jasondm007 I just thought this morning that we don't have to create a new string if we combine both of our version... just need to update the array in the AppleScript and set the text item delimter to tab and output the array as a string. So here is my new version

 

set my text item delimiters to tab

tell application "Finder" to set theSelection to selection as alias list

repeat with i from 1 to count of theSelection
	set item i of theSelection to POSIX path of item i of theSelection as string
end repeat

return theSelection as text

 

And an updated Workflow example here: https://nofile.io/f/aqMoJwmGf8O/File+Multi+Selection+&+OCR_Keywords.alfredworkflow

Edited by GuiB

Share this post


Link to post

Ok, I've tested it with a real action to do on each file. I didn't tested completely before, I just tested by outputing the path string to look at it, but now tested to do a real action on multiple files (copy them to a new file) and saw that the it didn't work on the last file in the list. So a little trimming to remove the whitespace on the file path worked. Therefore, here is an updated version that should work!

 

@Jasondm007 sorry for the little problems with my other versions. I think this one is good now, but let me know if you still have problem!

 

Here is the link to the new workflow: https://nofile.io/f/nTBEXw6Ku3U/File+Multi+Selection+&+OCR_Keywords.alfredworkflow

 

And here the modified script for the Run Script that execute the action

# Change IFS to TAB and expand into an array
IFS=$'\t' filesListArr=($@)

# Loop over the file list array
for file in "${filesListArr[@]}"
do
	trimmedPath="$(echo -e "${file}" | tr -d '[:space:]')"
	# Your script to be run
    automator -i "$trimmedPath" "/Users/NAME/Library/Services/NAME.workflow"
done

 

Share this post


Link to post

@GuiB This is awesome!! In fact, I think that Alfred ought to include more examples like this for those of us newbies or scripting novices (e.g., in the Getting Started or Examples menu)!! Thanks a ton!

 

I'm not sure if I'm doing something incorrectly, but I wasn't able to get the Run Script (bin/bash) to work as specified in your previous post above. By making the following small changes, however, it seems to be working great (changing the subsequent reference in the automator line from $trimmedPath to $file).

# Change IFS to TAB and expand into an array
IFS=$'\t' filesListArr=($@)

# Loop over the file list array
for file in "${filesListArr[@]}"
do
	trimmedPath="$(echo -e "${file}" | tr -d '[:space:]')"
	# Your script to be run
	automator -i "$file" "/Users/Name/Library/Services/Name.workflow"
done

Does this look correct to you? It seems to be working, but I'm concerned it will break! Thanks!

 

To make things easier for us to test, I've created a workflow that uses an actual bash script to move files to a user's downloads folder. The workflow has been uploaded for you here: https://nofile.io/f/ZWURw7ub90s. The file action at the top of the workflow operates perfectly (yellow - top). However, I'm having problems implementing your approach with a keyword (purple - middle). When it runs, it always drops one of the files (e.g., if run on 4 files, it will work for 3 of them, etc.). However, the hotkey - which runs the same bash script - operates perfectly (pink - bottom). Based on this example, how would you suggest applying your model to the keyword example in the uploaded workflow (purple - middle)? 

 

For quick reference - and for others who may not want to download the uploaded test workflow - below you will find a (1) screenshot of it, as well as the code from the (2) osascript and (2) bash scripts (purple - middle):

 

Screenshot

example.thumb.jpg.4348e3a964a671bc69490cfffa504890.jpg

 

 

Osascript

set my text item delimiters to tab

tell application "Finder" to set theSelection to selection as alias list

repeat with i from 1 to count of theSelection
	set item i of theSelection to POSIX path of item i of theSelection as string
end repeat

return theSelection as text

Bash Script

# Change IFS to TAB and expand into an array
IFS=$'\t' filesListArr=($@)

# Loop over the file list array
for file in "${filesListArr[@]}"
do
	trimmedPath="$(echo -e "${file}" | tr -d '[:space:]')"
	# Your script to be run
    mv -i "$file" ~/Downloads
done

 

Thanks for your help!

Share this post


Link to post
29 minutes ago, Jasondm007 said:

By making the following small changes, however, it seems to be working great (changing the subsequent reference in the automator line from $trimmedPath to $file).

By removing this small part, you made it work as before. Like you said, while doing a real test I saw that the last element in the list of selection wasn't working and found out it was because of problem with whitespaces. So I trimmed the surround spaces with the trimmedPath="$(echo -e "${file}" | tr -d '[:space:]')" line and the trimmedPath variable include the file variable but trimmed. However, now I did more tests and found out there's still a bug with this line and now use an alternative using piping to xargs to do the trimming instead.

 

Now, this seems to work, but again, let me know if you still have a problem!

 

Here is the updated script for the Run Script:

# Change IFS to TAB and expand into an array
IFS=$'\t' filesListArr=($@)

# Loop over the file list array
for file in "${filesListArr[@]}"
do
    trimmedPath="$(echo -e "${file}" | xargs)"
    # Your script to be run
    mv -i "$trimmedPath" ~/Downloads
done

 

Here is your script but updated with this fix: https://nofile.io/f/hjT4JFt6AVw/-+Example+File+Multi+Selection+Tests.alfredworkflow

 

And here is my workflow with this fix: https://nofile.io/f/c8K4KEpkjWa/Example+File+Multi+Selection.alfredworkflow

 

---------

To explain a little more why the other script doesn't work, but worked before on my side. The problem is that I was removing all the space in the file path, while the second one doesn't (it just trim the begining and end of the string; which is what I wanted in the begining, but did it too fast ;) ). I'm used to never insert space on my file name, so that's why it worked before. But, now I tested iton a file that's inside my "Google Drive" and it removed the space inside to output it like "GoogleDrive" and broke it. Now we should be good ;)

Edited by GuiB
Adding more explanation why the other script doesn't work

Share this post


Link to post

@GuiB Thanks a ton for tinkering with your script, and for the detailed explanation. This was tremendously insightful, and has helped me understand how to fix a bunch of my partially-operational workflows. This is awesome!

 

I hate to impose on you any more than I already have, but I am curious if you had any advice for dealing sending multiple files to AppleScripts (i.e., instead of sending the files to a bash script at the end, how might you split the file list for an AppleScript to operate)? A lot of my workflows use AppleScripts, and I'd love to make them work with multiple files, too. While I should probably start learning more bash, I often gravitate towards AppleScripts because I find them easier to understand and test with Mac's Script Editor (as I'm sure other newbies do as well). Alfred - the app, its developers, and the community - are great, but I wish the app contained more examples like the one that you created. Thanks again for all of your help!

Share this post


Link to post

@Jasondm007 Here is the same thing, but using AppleScript.

 

In short, change the last Run Script to an AppleScript one with this script:

on trim(theText)
  return (do shell script "echo \"" & theText & "\" | xargs")
end trim

on run argv
  set my text item delimiters to tab
  set theFileList to text items of (item 1 of argv)
  repeat with theFile in theFileList
    set fileAlias to (POSIX file trim(theFile) as alias)
	tell application "Finder" to move fileAlias to folder (path to downloads folder)
  end repeat
end run

 

Here is a new workflow with this inside in case it is easier to make it work: https://nofile.io/f/qvNgR5gw0pe/-+Example+File+Multi+Selection+Tests.alfredworkflow

 

 

This one should work and give you something to play around when using AppleScript ;)

 

All the best!

Edited by GuiB
Simplified the AppleScript a bit

Share this post


Link to post

@GuiB This is amazing!! Thanks a ton.

 

Am I correct to say that - in most applications of this method - only the highlighted portions of the following image would change (i.e., the portion of the script beginning with "set fileAlias ..." and ending with "... downloads folder)")? So, if I were to create another workflow, I'd be adding its new code to that highlighted portion and referencing each file with the "trim(theFile)" variable? Thanks!!

 

Script.jpg.37d84dd9878b6b1b8b2fc4694e02893d.jpg

 

 

Share this post


Link to post

@GuiB Please ignore that last question.

 

46 minutes ago, Jasondm007 said:

Am I correct to say that - in most applications of this method - only the highlighted portions of the following image would change (i.e., the portion of the script beginning with "set fileAlias ..." and ending with "... downloads folder)")? So, if I were to create another workflow, I'd be adding its new code to that highlighted portion and referencing each file with the "trim(theFile)" variable?

 

I think I understand how it works now. In most cases, it's just the "tell application ..." line(s) that will get changed, correct? And, subsequent references to each file are to the "fileAlias" variable?

 

For example, the code below follows your approach to open each file in the Preview app (nothing special about Preview here - I just wanted to make sure that I understood how everything worked). 

 

on trim(theText)
  return (do shell script "echo \"" & theText & "\" | xargs")
end trim

on run argv
  set my text item delimiters to tab
  set theFileList to text items of (item 1 of argv)
  repeat with theFile in theFileList
    set fileAlias to (POSIX file trim(theFile) as alias)
	tell application "Preview" to open fileAlias
  end repeat
end run

Thanks!

Share this post


Link to post

@Jasondm007 sorry, it seems I skipped your message, but to answer rapidly, yes that's pretty much what you need to do to change the action or application that will be run with the fileAlias. Simply change the line: tell application AppName to ActionToDoOn fileAlias

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...