Adding Finder Tage

Hi there,

Solved the initial issue… (May as well leave this in) What id really like to do is run a script that submits a value followed by a list whose multiple selections returned calculates a list of viable values (script already written) to be matched with the readings from the f0 tags printed to theFiles (as shown in the script below). I’d like to create a dialog/table that brings up a range of categories (labelled by tags) that each have their own row with 12 check boxes, each checkbox would correlate to one of the 12 possible f0 readings of a range. I would like to run a script that duplicated all file matches containing the specified tags (selected bu the checkbox) ordered by the category tag and copied to the category folders Any knowledge appreciated …

    tell application "Finder"
set fileName to fileName as text

 set currentFile to (get POSIX path of file fileName) 
	tell currentFile
			my tagCmd(it as text) 
	end tell

end tell

 on tagCmd(fileName)
do shell script "/usr/local/bin/tag -a " & "'" & f0 & "'" & space & fileName 

end tagCmd

I’m not sure that I understand your objective exactly but this script will check the selected files and if they do not have a file label, will tag them with the tags in f0. I find that the removing of the label index is flaky but YMMV. Substitute your own tags in f0.

Basically, it builds an alias list from the selected files and then cycles through them. If they have no label index then their path and the desired tags are fed to the tagCmd handler, where the path is converted to a posix path for the shell to run the tag command against.

set f0 to quoted form of "replacement, Blue, Reading Material"
tell application "Finder"
	set fList to selection as alias list
	
	repeat with eaFile in fList
		if label index of contents of eaFile is 0 then
			my tagCmd(eaFile, f0)
		else
			set label index of eaFile to 0
		end if
	end repeat
end tell

on tagCmd(eaFile, f0)
	set pp to quoted form of POSIX path of eaFile
	do shell script "/usr/local/bin/tag --add " & f0 & space & pp
end tagCmd

This snippet will use mdfind to find matching files on the desktop.

set f0 to quoted form of "replacement, Blue, Reading Material"
set dpath to POSIX path of (path to desktop as text)
do shell script "mdfind -onlyin " & dpath & " kMDItemUserTags == " & f0

Finally, this will put a copy of those matching files into a duplicates folder.

set f0 to quoted form of "replacement, Blue, Reading Material"
set dpath to POSIX path of (path to desktop as text)
set desto to POSIX path of (path to desktop as text) & "duplicates"
try
	do shell script "mdfind -onlyin " & dpath & " kMDItemUserTags == " & f0 & " -0 | xargs -0 -J % ditto % " & desto
end try

Thanks for your reply Mockman
Ahh kMDItemUserTags yes, thanks! The f0 property is calculated by analysing a file then using a mostPopularItemInList routine from some data of a csv column, the most popular item in the list is stored then set as a tag. My file database contains over 5000 files. Do you think tagging and using mdfind would be faster than using SQLite DB’s or JSON’s for matching the attributes against file paths?

I can’t speak to your latter options but (assuming your drive is indexed) mdfind is fast and its index is updated quickly upon any file changes. If its functionality is appropriate then it would be viable (and straightforward to work with).

Not sure what I’m missing but… When using finder (get selection) I could use the “if label index is 0” and “else set label index to” but I can’t use that with set fileName to fileName as text set currentFile to (get POSIX path of file fileName) is that because its expecting a list?

Is it possible to do some kind of parallel processing (like multithreading) with this script to the entire contents of several folders concurrently?

 `use AppleScript version "2.4" -- Yosemite (10.10) or later
 use framework "Foundation"
 use scripting additions

  property f0 : {}
  property fileName : {}

 tell application "Finder"
-- deletes previous sample files
set volume alert volume 0
delete (every item of folder "HD:Users:hm:folder:sample:" whose name extension is "wav")
delete (every item of folder "HD:Users:hm:folder:sample:" whose name extension is "csv")
delete (every item of folder "HD:Users:hm:folder:sample:" whose name contains "example")
delay 0.5

    set fileName to (choose file with prompt "Please Select a WAV file for Processing")
set audioWav to fileName
-- duplicate to Audition Folder
set audio_wav to duplicate audioWav to "HD:Users:hm:folder:sample:"



set f to (the first file of ¬
	container (alias "HD:Users:hm:folder:sample:") of ¬
	application "Finder" whose name ends with "wav")
set ti to text items of (get name of f)
if number of ti is 1 then
	set name of f to "example.wav"
      else
	set name of f to "example" & "." & "wav"
end if
  end tell
  tell application "Finder"
-- analyse file with pythons crepe and tensorflow
do shell script "/Users/hm/Library/Python/3.9/bin/crepe filename ~/folder/sample/example.wav -v -c 'full' -s '10'"
set recCsv to "/Users/hm/folder/sample/example.f0.csv"

-- read the CSV file. removing any rows in 3rd column with readings under 0.1

set my_data to read recCsv
set my_data to do shell script "awk -F ','  '$3>=0.1' " & (recCsv)'s POSIX path's quoted form
-- set my_data to do shell script "awk -F ','  '$1<=25.111' " & (recCsv)'s POSIX path's quoted form
-- set my_data to do shell script "awk '{ $2 = $2 * 2 }' " & (recCsv)'s POSIX path's quoted form

set csvData to paragraphs 2 thru -2 of my_data as list
-- reading all values in column 2 whose value from column 3 > 0.1
set freqData to {}

set oldDelims to AppleScript's text item delimiters
set AppleScript's text item delimiters to ","

repeat with a_reading in csvData
	
	-- averaging the value of "y" to its closest tonal value. Is there a way to make this section less convoluted? 
	set y to (text item 2 of a_reading)
	-- set y to y as integer
	if y ≥ 15.9 and y ≤ 16.8 then
		set y to "C0"
	else if y ≥ 16.81 and y ≤ 17.8 then
		set y to "C#0"
	else if y ≥ 17.81 and y ≤ 18.8 then
		set y to "D0"
	else if y ≥ 18.81 and y ≤ 19.9 then
		set y to "D#0"
	else if y ≥ 19.91 and y ≤ 21.21 then
		set y to "E0"
	else if y ≥ 21.22 and y ≤ 22.47 then
		set y to "F0"
	else if y ≥ 22.48 and y ≤ 23.8 then
		set y to "F#0"
	else if y ≥ 23.81 and y ≤ 25.22 then
		set y to "G0"
	else if y ≥ 25.23 and y ≤ 26.71 then
		set y to "G#0"
	else if y ≥ 26.72 and y ≤ 28.3 then
		set y to "A0"
	else if y ≥ 28.31 and y ≤ 29.99 then
		set y to "A#0"
	else if y ≥ 30.0 and y ≤ 31.78 then
		set y to "B0"
	else if y ≥ 31.79 and y ≤ 33.66 then
		set y to "C1"
	else if y ≥ 33.67 and y ≤ 35.66 then
		set y to "C#1"
	else if y ≥ 35.67 and y ≤ 37.78 then
		set y to "D1"
	else if y ≥ 37.79 and y ≤ 40.4 then
		set y to "D#1"
	else if y ≥ 40.41 and y ≤ 42.4 then
		set y to "E1"
	else if y ≥ 42.41 and y ≤ 44.93 then
		set y to "F1"
	else if y ≥ 44.94 and y ≤ 47.6 then
		set y to "F#1"
	else if y ≥ 47.61 and y ≤ 50.43 then
		set y to "G1"
	else if y ≥ 50.44 and y ≤ 53.43 then
		set y to "G#1"
	else if y ≥ 53.44 and y ≤ 56.6 then
		set y to "A1"
	else if y ≥ 56.61 and y ≤ 59.12 then
		set y to "A#1"
	else if y ≥ 59.13 and y ≤ 62.65 then
		set y to "B1"
	else if y ≥ 62.66 and y ≤ 66.36 then
		set y to "C2"
	else if y ≥ 66.37 and y ≤ 70.31 then
		set y to "C#2"
	else if y ≥ 70.32 and y ≤ 74.49 then
		set y to "D2"
	else if y ≥ 74.5 and y ≤ 78.91 then
		set y to "D#2"
	else if y ≥ 78.92 and y ≤ 83.61 then
		set y to "E2"
	else if y ≥ 83.62 and y ≤ 88.58 then
		set y to "F2"
	else if y ≥ 88.59 and y ≤ 93.85 then
		set y to "F#2"
	else if y ≥ 93.86 and y ≤ 99.43 then
		set y to "G2"
	else if y ≥ 99.44 and y ≤ 105.34 then
		set y to "G#2"
	else if y ≥ 105.35 and y ≤ 111.6 then
		set y to "A2"
	else if y ≥ 111.61 and y ≤ 118.24 then
		set y to "A#2"
	else if y ≥ 118.25 and y ≤ 125.27 then
		set y to "B2"
	else if y ≥ 125.28 and y ≤ 132.71 then
		set y to "C3"
	else if y ≥ 132.72 and y ≤ 140.61 then
		set y to "C#3"
	else if y ≥ 140.62 and y ≤ 145.97 then
		set y to "D3"
	else if y ≥ 145.98 and y ≤ 157.82 then
		set y to "D#3"
	else if y ≥ 157.83 and y ≤ 167.21 then
		set y to "E3"
	else if y ≥ 167.22 and y ≤ 177.15 then
		set y to "F3"
	else if y ≥ 177.16 and y ≤ 187.69 then
		set y to "F#3"
	else if y ≥ 187.7 and y ≤ 198.85 then
		set y to "G3"
	else if y ≥ 198.86 and y ≤ 210.67 then
		set y to "G#3"
	else if y ≥ 210.68 and y ≤ 223.2 then
		set y to "A3"
	else if y ≥ 223.21 and y ≤ 236.47 then
		set y to "A#3"
	else if y ≥ 236.48 and y ≤ 250.53 then
		set y to "B3"
	else if y ≥ 250.54 and y ≤ 265.44 then
		set y to "C4"
	else if y ≥ 265.45 and y ≤ 281.21 then
		set y to "C#4"
	else if y ≥ 281.22 and y ≤ 297.93 then
		set y to "D4"
	else if y ≥ 297.94 and y ≤ 315.66 then
		set y to "D#4"
	else if y ≥ 315.67 and y ≤ 334.43 then
		set y to "E4"
	else if y ≥ 334.44 and y ≤ 354.31 then
		set y to "F4"
	else if y ≥ 354.32 and y ≤ 375.37 then
		set y to "F#4"
	else if y ≥ 375.38 and y ≤ 397.7 then
		set y to "G4"
	else if y ≥ 397.71 and y ≤ 421.34 then
		set y to "G#4"
	else if y ≥ 421.35 and y ≤ 446.4 then
		set y to "A4"
	else if y ≥ 446.41 and y ≤ 472.94 then
		set y to "A#4"
	else if y ≥ 472.95 and y ≤ 501.06 then
		set y to "B4"
	else if y ≥ 501.07 and y ≤ 530.86 then
		set y to "C5"
	else if y ≥ 530.87 and y ≤ 562.43 then
		set y to "C#5"
	else if y ≥ 562.44 and y ≤ 595.87 then
		set y to "D5"
	else if y ≥ 595.88 and y ≤ 631.3 then
		set y to "D#5"
	else if y ≥ 631.31 and y ≤ 668.85 then
		set y to "E5"
	else if y ≥ 668.86 and y ≤ 708.62 then
		set y to "F5"
	else if y ≥ 708.63 and y ≤ 750.75 then
		set y to "F#5"
	else if y ≥ 750.76 and y ≤ 795.39 then
		set y to "G5"
	else if y ≥ 795.4 and y ≤ 842.69 then
		set y to "G#5"
	else if y ≥ 842.7 and y ≤ 892.8 then
		set y to "A5"
	else if y ≥ 892.81 and y ≤ 945.88 then
		set y to "A#5"
	else if y ≥ 945.89 and y ≤ 1002.14 then
		set y to "B5"
	else if y ≥ 1002.15 and y ≤ 1061.72 then
		set y to "C6"
	else if y ≥ 1061.73 and y ≤ 1124.86 then
		set y to "C#6"
	else if y ≥ 1124.87 and y ≤ 1191.75 then
		set y to "D6"
	else if y ≥ 1191.76 and y ≤ 1262.61 then
		set y to "D#6"
	else if y ≥ 1262.62 and y ≤ 1337.69 then
		set y to "E6"
	else if y ≥ 1337.7 and y ≤ 1417.23 then
		set y to "F6"
	else if y ≥ 1417.25 and y ≤ 1501.51 then
		set y to "F#6"
	else if y ≥ 1501.52 and y ≤ 1590.79 then
		set y to "G6"
	else if y ≥ 1590.8 and y ≤ 1685.38 then
		set y to "G#6"
	else if y ≥ 1685.39 and y ≤ 1785.6 then
		set y to "A6"
	else if y ≥ 1785.61 and y ≤ 1891.78 then
		set y to "A#6"
	else if y ≥ 1891.79 and y ≤ 2004.26 then
		set y to "B6"
	else if y ≥ 2004.27 and y ≤ 2123.44 then
		set y to "C7"
	else if y ≥ 2123.45 and y ≤ 2249.71 then
		set y to "C#7"
	else if y ≥ 2249.72 and y ≤ 2383.49 then
		set y to "D7"
	else if y ≥ 2383.5 and y ≤ 2525.22 then
		set y to "D#7"
	else if y ≥ 2525.23 and y ≤ 2675.38 then
		set y to "E7"
	else if y ≥ 2675.39 and y ≤ 2834.47 then
		set y to "F7"
	else if y ≥ 2834.48 and y ≤ 3003.14 then
		set y to "F#7"
	else if y ≥ 3003.15 and y ≤ 3181.57 then
		set y to "G7"
	else if y ≥ 3181.58 and y ≤ 3370.77 then
		set y to "G#7"
	else if y ≥ 3370.78 and y ≤ 3571.2 then
		set y to "A7"
	else if y ≥ 3571.21 and y ≤ 3783.55 then
		set y to "A#7"
	else if y ≥ 3783.56 and y ≤ 4008.54 then
		set y to "B7"
	else if y ≥ 4008.55 and y ≤ 4246.9 then
		set y to "C8"
	else if y ≥ 4246.91 and y ≤ 4499.43 then
		set y to "C#8"
	else if y ≥ 4499.44 and y ≤ 4766.98 then
		set y to "D8"
	else if y ≥ 4766.99 and y ≤ 5050.44 then
		set y to "D#8"
	else if y ≥ 5050.45 and y ≤ 5350.75 then
		set y to "E8"
	else if y ≥ 5350.76 and y ≤ 5668.92 then
		set y to "F8"
	else if y ≥ 5668.93 and y ≤ 6006.02 then
		set y to "F#8"
	else if y ≥ 6006.03 and y ≤ 6363.16 then
		set y to "G8"
	else if y ≥ 6363.17 and y ≤ 6741.53 then
		set y to "G#8"
	else if y ≥ 6741.54 and y ≤ 7142.4 then
		set y to "A8"
	else if y ≥ 7142.41 and y ≤ 7567.11 then
		set y to "A#8"
	else if y ≥ 7567.12 and y ≤ 8017.07 then
		set y to "B8"
	end if
	set y to y as text
	-- rounds each reading to its tempered tonal counterpart
	set end of freqData to y
	
end repeat

  	set L to freqData

 end tell

   -- finds the mostPopularItemInList
  set theList to {}
 repeat 50 times
 	set theList to theList & items of L
 end repeat

 mostPopularItemInList(theList)

 to mostPopularItemInList(x)
script accellerator
	property theList : x
	property originalItems : {}
	property originalItemsCount : {}
	on indexof(theItem, theList)
		set text item delimiters to return
		set theList to return & theList & return
		set text item delimiters to {""}
		try
			-1 + (count (paragraphs of (text 1 thru (offset of (return & theItem & return) in theList) of theList)))
		on error
			0
		end try
	end indexof
	to greaterInteger()
		set largerItem to 0
		set largerItemIndex to 0
		repeat with i from 1 to count originalItemsCount
			if originalItemsCount's item i > largerItem then
				set largerItem to originalItemsCount's item i
				set largerItemIndex to i
			end if
		end repeat
		originalItems's item largerItemIndex
	end greaterInteger
end script

repeat with i from 1 to count accellerator's theList
	considering case
		if accellerator's theList's item i is not in accellerator's originalItems then
			set accellerator's originalItems's end to accellerator's theList's item i
			set accellerator's originalItemsCount's end to 1
		else
			set ind to accellerator's indexof(accellerator's theList's item i, accellerator's originalItems)
			set accellerator's originalItemsCount's item ind to ((accellerator's originalItemsCount's item ind) + 1)
		end if
	end considering
end repeat

set f0 to paragraphs 2 thru -2 of return & accellerator's greaterInteger() as text

    end mostPopularItemInList

– sets mostPopularItemInList to Finder tag

tell application “Finder”

set fileName to fileName as text
set currentFile to (get POSIX path of file fileName) as list
tell currentFile
	
	my tagCmd(it as text)
end tell

 end tell

 on tagCmd(f)
  do shell script "/usr/local/bin/tag -a " & "'" & f0 & "'" & space & quoted form of POSIX path of             fileName -- "(get selection)" -- posix path convert path with colon to use in shell
end tagCmd`

Offhand, I would guess that it’s because the selection is a file object and thus, has those properties (including label index) whereas the others are text strings.

As to multi-processing… my understanding is that applescript is resolutely anti-parallel processing. The shell can do some things in parallel but I don’t know if you can spawn multiple processes from applescript that take full advantage of parallelism.