Misha Posted July 19, 2017 Posted July 19, 2017 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?
deanishe Posted July 19, 2017 Posted July 19, 2017 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. Misha 1
GuiB Posted July 20, 2017 Posted July 20, 2017 (edited) 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 July 20, 2017 by GuiB Misha 1
Misha Posted July 21, 2017 Author Posted July 21, 2017 (edited) 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 July 21, 2017 by Misha
Jasondm007 Posted December 4, 2018 Posted December 4, 2018 @GuiB Thanks for posting the following workflow: On 7/19/2017 at 9:43 PM, GuiB said: Here is the workflow: https://nofile.io/f/O7scHb0o3rm/File+Selection+&+OCR_Keywords.alfredworkflow 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)!!
GuiB Posted December 4, 2018 Posted December 4, 2018 (edited) @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 December 4, 2018 by GuiB
Jasondm007 Posted December 4, 2018 Posted December 4, 2018 @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!
GuiB Posted December 4, 2018 Posted December 4, 2018 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!
GuiB Posted December 4, 2018 Posted December 4, 2018 (edited) @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 December 4, 2018 by GuiB
GuiB Posted December 4, 2018 Posted December 4, 2018 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 Jasondm007 1
Jasondm007 Posted December 5, 2018 Posted December 5, 2018 @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 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!
GuiB Posted December 5, 2018 Posted December 5, 2018 (edited) 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 December 5, 2018 by GuiB Adding more explanation why the other script doesn't work Jasondm007 1
Jasondm007 Posted December 5, 2018 Posted December 5, 2018 @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!
GuiB Posted December 5, 2018 Posted December 5, 2018 (edited) @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 December 5, 2018 by GuiB Simplified the AppleScript a bit
Jasondm007 Posted December 5, 2018 Posted December 5, 2018 @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!!
Jasondm007 Posted December 5, 2018 Posted December 5, 2018 @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!
GuiB Posted February 24, 2019 Posted February 24, 2019 @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
evanfuchs Posted June 17, 2019 Posted June 17, 2019 On 12/4/2018 at 11:33 PM, GuiB said: 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 Any chance of resharing this example workflow? The link is dead. Thanks!
GuiB Posted June 17, 2019 Posted June 17, 2019 @evanfuchs, yeah nofile.io seems to be down... not sure they will get back, but here is what I think are the 2 last scripts from my posts above. My answer regarding @Jasondm007 's script (using AppleScript): https://d.pr/f/2yFEeJ My other script (using Bash): https://d.pr/f/yLrWRS Hope this help! evanfuchs 1
deanishe Posted June 18, 2019 Posted June 18, 2019 9 hours ago, GuiB said: yeah nofile.io seems to be down Namecheap has suspended their domain, it seems.
GuiB Posted June 19, 2019 Posted June 19, 2019 @deanishe, yep this is what I've seen yesterday as well. It seems to be on and off since may. I won't get my hopes up that they will come back... we will see
Jasondm007 Posted December 7, 2019 Posted December 7, 2019 @GuiB I was wondering if I could ask a quick question related to our previous discussion/working examples above? More specifically, I occasionally have issues when trying to use your working example to connect a File Action to Run Script set as an AppleScript. Namely, the script often only runs on the first file selected and not the others. For example, this morning I was trying to create a quick workflow that will work for multiple selections at a time with a (1) a keyword through Finder, and (2) a file action. The workflow merely places the files on the clipboard as images (I have one app in particular that is a little finicky about pasting things). In any case, it works perfectly from the keyword for multiple selections. However, it only works for the first selection when run from a file action. It's virtually identical to your working example (which moved files to the user's downloads folder). I've highlighted the only real difference below: Any ideas what might be causing the problem? Does the text from the file action have to be processed before being handed off? I tried creating another step after the file action, so that I could try and get the list of files to look identical to the list that is handed off by the keyword-based version, but I was never quite able to get it to work for multiple selections at a time. I've uploaded the workflow here: Download Workflow Hope this finds you well. Thanks for any help you can lend!
GuiB Posted December 8, 2019 Posted December 8, 2019 @Jasondm007, you problem is that when you are directly connecting to the File Action you are receiving a list of files in "argv", but on the second example ("imc") you are sending a tab delimited list of file paths that consist as a single string as input. Therefore, on your first example you can iterate over the list input of you script and not just the first argument ("argv 1"). Here is a modified version: https://d.pr/f/0BOBGT I added a delay to better make sure the item has time to be copied (I didn't have all the items on my clipboard viewer if not), but you can play with it to make it work for your case. Jasondm007 1
Jasondm007 Posted December 9, 2019 Posted December 9, 2019 @GuiB Thanks a ton for taking the time out to take a look at this for me. Your explanation and this working example is incredibly helpful. Much appreciated. By chance do you have any recommendations for how to test for these types of variable-related problems? I use the debugger and often create intermediate steps where I copy a variable to the clipboard, so that I can make sure that everything looks OK. However, these problems drive my crazy!! 🤪 Thanks again!!
GuiB Posted December 9, 2019 Posted December 9, 2019 @Jasondm007 honestly I don't have many tricks for trying to get some outputs to the debugger and carefully looking at the information there. Sometimes I look at what is happening before, sometimes after a node, trying to output a variable and analyzing it to see if it's right, adding tests inside the script to try to pinpoint where the problem occurs (see if a loop is looping correctly, if a variable is set correctly...)... In this case, you could see that from the "imc" Keyword node a string was output with paths separated by tab, but on the "Image..." File Action node you could see that the paths are separated by "comma" in the debugger (if you connect the Debug node just after the File Action). This way you have a little cue that the outputs are different. Then you can inspect the "item 1 of argv" and see if they match and if not try to find out why they are different. With that said, keep in mind that from an Alfred node that output a list of items you would get a List, but when chaining multiple nodes (different Run Scripts or other actions) one output is passed to the next node as one string. So, in order to get multiple items we have to build this string we can manipulate it in the next node to retrieve the different items (that's why I'm passing the paths with tabs as separators as a trick to pass multiple items so we can easily split them afterward in the next node). You can use any delimiter that you want of passing JSON string or something else (like we talked on this thread: To get back to your workflow above, actually you don't have to pass the output of your AppleScript from your "imc" keyword node and depending on what you want to achieve it could be easier to directly loop over the selection list that you get from the Finder instead of modifying the list to a single string with tab delimiter (especially if you want to connect it to another AppleScript). Here is a modified workflow to show you how it looks if you use the selection directly: https://d.pr/f/pvtilq Also, I don't remember exactly why I added the Trim function to make sure to trim the files path (maybe to make sure one of the paths doesn't have an extra whitespace in it in case we output as one string), but if you use the passed list from Alfred file action or the Finder selection, then you shouldn't have to trim the paths. Hope this helps a bit! Best Jasondm007 1
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now