AppleScript returns different results manually vs hazel

Get help. Get answers. Let others lend you a hand.

Moderator: Mr_Noodle

Hello,

I have a simple AppleScript that I am having trouble getting Hazel to match.

If I use the commented out line to manually set the path to a file and comment out the handler information the script runs as expected and returns the desired results in the code below. However, when I create a hazel rule that "Passes AppleScript" and point the rule to the AppleScript below it does not match. The rule will match if I swap the position of true and false but it then moves the wrong files to the desired location. It should be something simple with the syntax but I can't get it to work as expected. I have read through "Using AppleScript or JavaScript" but am still missing something.

Now, this simple rule should really be accomplished through Hazel's UI. However, my goal is to really fine tune a folder structure consisting of thousands of files and multiple levels. I would like to be able to use the same criteria throughout multiple rules at different levels for different reasons and by able to dynamically update the "matching string" criteria dynamically. That way I don't have to manually update multiple rules with the same information.

Ideally in my mind any "names contains" rules could be compared against a text file or two containing a list of strings. The appropriate "Passes AppleScript" rules would be set up either internally or externally and pointed to the correct text file so all I have to do is update ether text document.

Is there an easier way?

Code: Select all
on hazelMatchFile(theFile, inputAttributes)
   
   --set pathList to quoted form of POSIX path of (choose file with prompt "Please choose a file:" default location (path to desktop))   
   
   set criteria to {"Bob", "Susan"}
   
   repeat with i from 1 to (count criteria)
      if theFile contains item i of criteria then
         return true
         exit repeat
      else
         return false
      end if
   end repeat
   
end hazelMatchFile
jfisher
 
Posts: 55
Joined: Sat Feb 25, 2017 7:47 pm

I suggest printing/displaying the variables in the script along the way to see where things are going wrong. If you turn on debug mode (https://www.noodlesoft.com/kb/hazel-debug-mode/), it will show the output of the AppleScript in the logs.
Mr_Noodle
Site Admin
 
Posts: 11255
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City

Thank you for the tip. I did not know that was there.

However, the debug log does not anything because the AppleScript rule would not match. I tried a few other things and noticed that my AppleScript is only trying to match against the first item in the list/array.

So I am trying to research why.
jfisher
 
Posts: 55
Joined: Sat Feb 25, 2017 7:47 pm

If the script is run at all, it should show any output. If it's not running then that probably indicates a previous condition is already causing the rule to not match. In that case, use the preview function to test that out.
Mr_Noodle
Site Admin
 
Posts: 11255
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City

I have been using the preview function to test a lot of my rules and in this case the type is folder and sunfolser depth lines both pass and the script “does not match”. I was thrown off that no output was given in the debug window. Even trying to force the rule to run.
jfisher
 
Posts: 55
Joined: Sat Feb 25, 2017 7:47 pm

Did you add lines to your script to output anything? You'll need to do that to see anything in the logs. I'd add statements to print out variables at different points in the script.
Mr_Noodle
Site Admin
 
Posts: 11255
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City

I've been trying to figure this out and have been reading on forums about different ways to read strings from a text file.

The plain text file I'm referencing contains the words below on separate lines/paragraphs.

Apple
Pears
Oranges

I've been trying to test this inside AppleScript and my current code looks like so.

Code: Select all
--on hazelMatchFile(theFile, inputAttributes)

-- set theFile location:
set theFile to POSIX path of (choose file with prompt "Select file")

-- set matchFile location:
set matchFile to "Volumes:Backups:Hazel:AppleScripts:Match Files:Fruit.txt"

-- read contents of matchFile:
set theFileContents to (read file matchFile)

--display dialog theFileContents

-- break out the lines/paragraphs of text:
set theLines to paragraphs of theFileContents

-- iterate through theLines, one by one:
repeat with eachLine in paragraphs of theLines
   if theFile contains theLines then
      return true
      --display dialog theLines
      exit repeat
   else
      return false
      
   end if
   exit repeat
end repeat

--end hazelMatchFile



Inside AppleScript the the script always returns false. I thought that by breaking the contents os the text file into paragraphs the script would be able to test if theFIle contains line 1, if not iterate to line 2 etc. but I am not sure if it is breaking up the test file correctly and instead trying to see if the entire file matches.

When I run this inside Hazel get that file did not match any rules which is expected based on manual testing. Is there a small error in my code? I have tried with the handler hazelProcessFile as well as passing attributes into the script from the UI.


2018-01-24 19:44:11.785 HazelHelper[2149] DEBUG: Thread 0x604000066780: Run worker for folder: /Users/jfisher/Downloads/Unsorted
2018-01-24 19:44:11.819 hazelworker[2648] ###main load address: 0x1073b7000
2018-01-24 19:44:11.821 hazelworker[2648] ###Noodle load address: 0x1074d9000
2018-01-24 19:44:11.821 hazelworker[2648] ###CK load address: 0x107499000
2018-01-24 19:44:11.829 hazelworker[2648] DEBUG: Program is licensed.
2018-01-24 19:44:11.869 hazelworker[2648] DEBUG: Unexpected type for Mail download URL: (null)
2018-01-24 19:44:11.872 hazelworker[2648] Processing folder Unsorted (forced)
2018-01-24 19:44:11.872 hazelworker[2648] DEBUG: Pausing to wait for things to settle down.
2018-01-24 19:44:13.878 hazelworker[2648] DEBUG: Processing directories: (
"/Users/jfisher/Downloads/Unsorted"
)
2018-01-24 19:44:13.880 HazelHelper[2149] DEBUG: Checking events for path /Users/jfisher/Downloads/Unsorted, folder Unsorted
2018-01-24 19:44:13.881 hazelworker[2648] DEBUG: Received file event: {
date = "2018-01-25 00:44:11 +0000";
path = "<ComNoodlesoft_NoodlePathSet: 0x7ff80fc21740>\n /Users/jfisher/Downloads/Unsorted : 18446744073709551615\n";
}
2018-01-24 19:44:13.881 hazelworker[2648] DEBUG: About to process directory /Users/jfisher/Downloads/Unsorted
2018-01-24 19:44:13.882 hazelworker[2648] DEBUG: .DS_Store: File is hidden/invisible. Skipping.
2018-01-24 19:44:14.067 hazelworker[2648] DEBUG: Picture of apple.png: Did not match any rules.
2018-01-24 19:44:14.104 hazelworker[2648] DEBUG: Pears in a bowl.png: Did not match any rules.
2018-01-24 19:44:14.105 hazelworker[2648] DEBUG: Directory /Users/jfisher/Downloads/Unsorted processed in 0.223616 seconds
2018-01-24 19:44:14.105 HazelHelper[2149] DEBUG: Checking events for path /Users/jfisher/Downloads/Unsorted, folder Unsorted
2018-01-24 19:44:14.106 hazelworker[2648] DEBUG: Sending metrics to scheduler. Next scheduled run: 4000-12-31 19:00:00.000
2018-01-24 19:44:14.107 HazelHelper[2149] DEBUG: Received metrics for folder /Users/jfisher/Downloads/Unsorted: {
directoryDepth = 18446744073709551615;
requestedSchedulingTime = "4001-01-01 00:00:00 +0000";
triggerPaths = "<ComNoodlesoft_NoodlePathSet: 0x6000000282a0>\n";
unavailablePaths = "{(\n)}";
}
2018-01-24 19:44:14.107 HazelHelper[2149] DEBUG: Timer scheduled for folder /Users/jfisher/Downloads/Unsorted at 4001-01-01 00:00:00 +0000
2018-01-24 19:44:14.107 hazelworker[2648] Done processing folder Unsorted
2018-01-24 19:44:14.110 HazelHelper[2149] DEBUG: Thread 0x604000066780: Task removed: [2648]
2018-01-24 19:44:29.911 HazelHelper[2149] DEBUG: Deploy folders: (
Unsorted,
Trash
)
2018-01-24 19:44:29.911 HazelHelper[2149] DEBUG: Thread 0x604000066780: Deploying worker for folder: /Users/jfisher/Downloads/Unsorted
2018-01-24 19:44:29.911 HazelHelper[2149] DEBUG: Thread 0x604000066780: Deploying worker for folder: /Users/jfisher/.Trash
2018-01-24 19:44:29.912 HazelHelper[2149] DEBUG: Thread 0x604000066780: FOLDERS SYNCED: (
Trash,
Unsorted
)
jfisher
 
Posts: 55
Joined: Sat Feb 25, 2017 7:47 pm

While debugging your script is outside the scope of support I can give, I do see you doing "theFile contains...". I don't think that would work as "theFile" is a file alias. At best, it would be converted to a path which definitely won't contain any lines.

My guess is you need to read the contents of both files into strings then do the comparisons after that.
Mr_Noodle
Site Admin
 
Posts: 11255
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City

Thank you for the reply. I haven’t been able to find as much time as I would like to work on this but your comments are making things more clear.

To clarify, hazelMatchFile(theFile, inputAttributes) passes only the alias path to “theFile” if inputAttributes are left blank in the Hazel UI?

If inputAttributes are selected in the Hazel UI, they are passed in as a list called inputAttributes?

If I selected the “file name” inputAttribute to be passed to the script should I be checking if the inputAttribute contains a paragraph from my matchFile?

I appreciate the help.
jfisher
 
Posts: 55
Joined: Sat Feb 25, 2017 7:47 pm

It doesn't matter if you pass in the filename separately. It's just a string with the filename. I think you are comparing apples and oranges (file name vs file contents). As far as I understand it, you'll need to get the contents of both files in the same way, then compare those.
Mr_Noodle
Site Admin
 
Posts: 11255
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City

If anyone is interested I was able to make the following code accomplish what I was after. Hazel passes the alias path to the file that matched and in my case only the "name" inputAttribute to the script. The script checks if the filename contains any of the strings in a return delimited text file and returns true if it does and leaves return as default if it does not.

I have a plethora of files to move around and want to use the same criteria (text) files in different locations for different reasons and found it was easier to have a text file drive the match criteria from one location then to ensure each of my hazel rules was set up with same attributes. I know that sync rules is an option but for the file structure I'm looking for this made things more simple.

Code: Select all
on hazelMatchFile(theFile, inputAttributes)
   
   set match to false
   
   -- set fileName to first item of inputAttributes list
   set fileName to item 1 of inputAttributes
   
   -- set path to matchFile:
   set matchFile to paragraphs of (read alias "***file path here***")
   
   -- iterate through the matchList, textstring by textstring:
   repeat with textString in matchFile
      if textString is in fileName then
         set match to true
      end if
   end repeat
   
   return match
   
end hazelMatchFile
jfisher
 
Posts: 55
Joined: Sat Feb 25, 2017 7:47 pm


Return to Support