FileManagerLib for tags and name extension

Does anyone know how to use FileManagerLib to only search for files with a certain name extension in the results of

folder

set cFol to choose folder
set theFiles to objects of cFol result type files list with searching subfolders without include folders

Also is it possible with FileManagerLib using a list eg “cat”, “dog”, “mouse” to search for files containing a list item as a tag?

Thank Fredrik,

Any idea why this doesn’t work?

`use theLib : script "FileManagerLib" version "2.3.5"
use scripting additions

set cFol to choose folder
set theContents to objects of cFol result type files list with searching subfolders without include folders
set theFiles to {}
repeat with i from 1 to count theContents
	if ((item i of theContents) contains ".wav") then
		set end of theFiles to item i of theContents
	end if
end repeat
return theFiles`

And any idea if its possible to search KMDItemUserTags?

It doesn’t work because you try to compare different things: item i of theContents (which is file reference) and “.wav” (which is string). Anyway, exists better workaround which doesn’t need the repeat loop. It uses NSPredicate filter:

use theLib : script "FileManagerLib" version "2.3.1"
use framework "Foundation"
use scripting additions
property NSPredicate : a reference to NSPredicate of current application

set cFol to choose folder

set theContents to objects of cFol result type urls array with searching subfolders without include folders

-- Filter case-insensitively for items with "wav" extensions.
set thePredicate to NSPredicate's predicateWithFormat:("pathExtension ==[c] 'wav'")
set theFiles to theContents's filteredArrayUsingPredicate:(thePredicate)

return theFiles as list

Thanks Kniazidis

That works great on its own but when I add it to a prepareToProcessFiles handler on a run script theFiles doesn’t yield any file results to be processed individually in the following processAFile handler. Any idea what a workaround might be?
D

Hey Fredrik,

Thanks. I’ll take a look at the MetaDataLib, just wasn’t sure if the FileManagerLib’s tags suite could perform a search by tag

You are asking me to guess what handler (prepareToProcessFiles) you wrote. But I don’t have telepathic abilities.

2 Likes

Your suggested code is the contents of the prepareToProcessFiles handler, which returns theFiles

Then the run script then enters a loop with repeat with aFile in theFiles

The event log goes through each file with the error
Get name of file “HD:Users:me:Desktop:1:New Folder With Items:Audio.wav”
! Unable to coerce the data to the desired type (errAECoercionFail:-1700)

The resulting list (theFiles as list) is a list of Posix file references that do not have a name property. You can convert them to a list of Finder file references that have this property:

set theNames to {}
repeat with nextFile in theFiles
	tell application "Finder" to set end of theNames to name of file (nextFile as text)
end repeat
return theNames

Also, you can convert them to a list of System Events references that also have this property. But, the most efficient way is to get the names directly from the list of NSURL references. To do this, theFiles should not be coecated as list, but left as is:

use theLib : script "FileManagerLib" version "2.3.1"
use framework "Foundation"
use scripting additions
property NSPredicate : a reference to NSPredicate of current application

set cFol to choose folder

set theContents to objects of cFol result type urls array with searching subfolders without include folders

-- Filter case-insensitively for items with "wav" extensions.
set thePredicate to NSPredicate's predicateWithFormat:("pathExtension ==[c] 'wav'")
set theFiles to theContents's filteredArrayUsingPredicate:(thePredicate)
-- set theFiles to theFiles as list  -- do  not coerce

set theNames to {}
repeat with nextFile in theFiles
	set end of theNames to (nextFile's lastPathComponent()) as text
end repeat
return theNames

NOTE: You can also parse the name using AppleScript’s Text Item Delimiters. In short, there are several ways to get the Posix-file’s name.

Thanks for tha, I really appreciate your help. my aim was to take the file references in theFiles and run each file through a shell script perform a few AppleScript tasks then make xattr additions to each file. Im still trying to figure out the most efficient way to write the script for large batch processing, but as your script yielded 35000 .wav results in under 30 seconds am hoping I can use it in my applet

Then, why not shell solution instead of FileManagerLib?

set chosenFolder to POSIX path of (choose folder)

set theWAVs to paragraphs of (do shell script "find " & quoted form of chosenFolder & " -type f -name '*.wav'")

repeat with theWAV in theWAVs
	do shell script "xattr -w 'myTag' 'myTagValue' " & quoted form of theWAV
end repeat

.
Building the multiple path, you can apply xattr tags at once, as well:

set chosenFolder to POSIX path of (choose folder)

set theWAVs to paragraphs of (do shell script "find " & quoted form of chosenFolder & " -type f -name '*.wav'")

set compositePath to ""
repeat with theWAV in theWAVs
	set compositePath to compositePath & quoted form of theWAV & space
end repeat

do shell script "xattr -w 'myTag' 'myTagValue' " & compositePath

.
Using AppleScript’s text item delimiters you can eliminate the repeat loop:

set chosenFolder to POSIX path of (choose folder)

set theWAVs to paragraphs of (do shell script "find " & quoted form of chosenFolder & " -type f -name '*.wav'")

set ATID to AppleScript's text item delimiters
set AppleScript's text item delimiters to return
set theWAVs to text items of theWAVs
set AppleScript's text item delimiters to quote & space & quote
set compositePath to quote & (theWAVs as text) & quote
set AppleScript's text item delimiters to ATID

do shell script "xattr -w 'myTag2' 'myTagValue2' " & compositePath

Appreciated, any suggestions are welcome. I have probably over 100,000 samples that I need to run through a python based pitch estimation app, which produces a CSV with pitch readings that I organise into the frequencies with the highest probability score, take the top readings, round the readin from hz to the nearest note, take the most popular/frequent frequency and label the wav file with its note, I also label what kind of drum it is so once all the samples are labelled I can create an interface that allows me to select certain drums tuned to certain intervals using some maths. Someone suggested asobjc on here mixed with json. Not sure what the best approach is as I have so many thousands of files. The python app can batch analyse possibly multi thread, dunno if a database would be a good angle. My aim is to avoid dissonance in the eq spectrum in my compositions by using percussive samples that are harmonically compatible with the other instrument info

That’s cool, but how can I do this?

`use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
-- use script "FileManagerLib" version "2.3.5"
use scripting additions
property f0 : {}
property fileName : {}
property my_data : {}
property csvData : {}
property theList : {}


on prepareToProcessFiles(theFiles)
	
	set chosenFolder to POSIX path of (choose folder)
	
	set theWAVs to paragraphs of (do shell script "find " & quoted form of chosenFolder & " -type f -name '*.wav'")
	set ATID to AppleScript's text item delimiters
	set AppleScript's text item delimiters to return
	set theFiles to text items of theWAVs
	-- set AppleScript's text item delimiters to quote & space & quote
	-- set compositePath to quote & (theWAVs as text) & quote
	-- set AppleScript's text item delimiters to ATID
	--	
	return theFiles
end prepareToProcessFiles

on processAFile(theFile)
	
	tell application "Finder"
		set volume alert volume 0
		delete (every item of folder ((path to desktop folder as text) & "conv:") whose name extension is "csv")
		
		
		set audioWav to theFile -- choose file with prompt "Please Select a WAV file for Processing" default location alias ((path to desktop folder as text) & "conv:")
		--set audioWav to fileName as text
		--set audioWav to quoted form of POSIX path of audioWav
	end tell
	-- generate CSV
	tell application "Finder"
		do shell script "~/Library/Python/3.9/bin/crepe filename " & audioWav & space & "-v -V  -c 'full' -s '10' -o ~/Desktop/conv/"
		
		try
			set csv to (file 1 of folder ((path to desktop folder as text) & "conv:") whose name ends with "csv") as text
		on error
			return false
		end try
		set csv to quoted form of POSIX path of csv
		set my_data to do shell script "cat " & csv & " | sort -t, --key=3,3 -gr | head -n10"
		set csvData to paragraphs 2 thru -2 of my_data as list
	end tell

`

I want to take the items in theWAVs and process each one individually. Once Ive ran the python shell script on theFile I can get the data I need using its generated CSV file with some shell and AS and then I have to attach the data as a tag to the POSIX path of theFile in shell. I thought the posix items in theWAVs would be usable with the framework in the script.Would I have to get a list of directories and subdirectory files with .wav using using AS and HFS paths before handing it over to the prepare a file handler? Ideally id like to use filemanagerlib/nspredicate but am unsure how to coerce the nsurl array into a list of hfs path items to be passed on to the prepareAFile handler