AppleScript string comparison

Discussion in 'Mac Programming' started by Jon Trepte, Sep 17, 2014.

  1. Jon Trepte, Sep 17, 2014
    Last edited by a moderator: Sep 17, 2014

    Jon Trepte macrumors newbie

    Joined:
    Sep 17, 2014
    #1
    I have the following code to compare 2 strings
    Code:
    set s1 to "A.P.E."
    set s2 to "A.P.E_"
    log s1
    log s2
    
    set a1 to ASCII number "."
    set a2 to ASCII number "_"
    
    log s1 < s2
    considering case
    	log s1 < s2
    	log s1 is less than s2
    end considering
    
    and I get the following strange results
    (*A.P.E.*)
    (*A.P.E_*)
    tell current application
    	ASCII number "."
    		--> 46
    	ASCII number "_"
    		--> 95
    	(*false*)
    	(*false*)
    	(*false*)
    end tell
    
    can anybody out there please tell me what is going on here as I think s1 should be less than s2 as they differ in the 6th char (46 and 95) and I think 46 is less than 95. Maybe I'm going senile!!!!
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    You're assuming that AppleScript uses ASCII collation order for strings. It doesn't.

    It uses the language-specific collation order for your currently selected language. If you've selected English as your primary language, then it uses that collation order (aka "sort order"). You might think that English collation order would be the same as ASCII but it isn't.

    I googled the search terms applescript collation order. The two of the top results (not necessarily in this order) are:
    https://developer.apple.com/library...ScriptLangGuide/reference/ASLR_operators.html
    http://lists.apple.com/archives/applescript-users/2008/Oct/msg00340.html

    The first is a reference that explains how AppleScript collates (sorts or compares) strings (text). The second is a post to an AppleScript mailing list that shows the actual results for the English language collation order. In particular, note where '_' and '.' are located.

    If you need ASCII collation or comparison, you'll have to use something other than AppleScript's builtin operators. For suggestions, you'll first have to explain what you're trying to do, so we know what tools would be applicable.


    I don't know of a reference that lists OS X's collation order for English, or any other language. If you really need to know what it is, you should write a program that produces it.

    If you want to try an experiment, set the "Order for sorted lists" in System Preferences to Hawaiian and observe the effect it has on the collation order for letters. For example, sort a Finder window by name after choosing Hawaiian.
    http://en.wikipedia.org/wiki/Hawaiian_language#Orthography
     
  3. Jon Trepte thread starter macrumors newbie

    Joined:
    Sep 17, 2014
    #3
    Hi chown33,
    Firstly let me thank you for your time and effort.
    OK here is what I'm trying to do. I have an iTunes library and I wish to put it on my NAS. However when I did I found that my NAS is case sensitive and iTunes could not find some 5,000 songs from 88,000. So I used find in terminal to give me a text file with every song listed in the Music folder. This appears to be sorted in some particular order, probably the one you suggested. Now what I needed to do was go through every song in the iTunes library and compare it's location to the one in finder. I needed to do a binary search on my list created from the file and this is where I noticed strange things happening. So what I need is a string comparison function that uses the same collation order as finder did to give the list of files. I hope this helps.
     
  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    Some programs misbehave on case-sensitive file systems. iTunes may be one. Hard to say without knowing versions.

    One solution is to create a disk-image on the NAS, format it HFS+ case-insensitive, and put the iTunes library there.


    The output of find uses the order that entries are stored in the directory, unless told otherwise (-s option). You didn't show the 'find' command, so I can't suggest anything other than generalized comments.

    Nope. It's the order that HFS+ stores directory entries in. The details of the B-tree enetries for the catalog file are documented, and it's definitely NOT Finder's sorting order. It's not AppleScript's string comparison ordering, either.

    If you assumed a sorted order, you made an error. If you're planning to do a binary search, it's mandatory that the list be collated in the same order as the string-comparison function you plan to search with. Close isn't good enough; the collation must be exactly the same.

    The obvious solution here is to sort the list into the order needed.

    Manually go through every song? Or with a program? What language is the program written in? I could assume AppleScript, but I could be wrong.

    What is it's location "in finder"? Do you mean "in the output of the 'find' command", or do you mean "the sorted result in a Finder window"? I don't know whether you really mean "Finder" (which seems irrelevant) or whether that's a typo for "find" (because the list was produced by 'find').

    As noted above, the same collation order is mandatory.

    Again the ambiguous term "finder". You used "find", not "Finder", to produce the list, as far as I can tell. Accuracy is important in programming.

    You also assumed that find's output is sorted in the same collation order that AppleScript's string comparison uses.

    The obvious solution at this point, and with no other information, is to assume the list produced by 'find' (not "finder") isn't sorted at all. Sort the list in AppleScript, using AppleScript's own comparison operation, before using it for binary search.
     
  5. Jon Trepte, Sep 21, 2014
    Last edited by a moderator: Sep 22, 2014

    Jon Trepte thread starter macrumors newbie

    Joined:
    Sep 17, 2014
    #5
    Once again many thanks for your reply.
    I used find in terminal like this having chanced to the iTunes music folder
    Code:
    find . -type f > AllFiles.txt
    and this gave me a list of all my files
    I then used textedit to remove the file prefix "Music:"
    and saved the file. The file seemed to be somewhat sorted but not in the same collation order as AppleScript.
    As you suggest I will have to get a sort algorithm in AppleScript to sort my list.
    Once I get this list sorted I was going to write an AppleScript that would go through every track in the iTunes library along the lines of

    Code:
    tell application "iTunes"
    	activate
    	
    	set nCount to count tracks of playlist 1
    	log nCount
    	set nErr to 0
    	
    	repeat with i from 1 to nCount
    		set aTrack to track i of playlist 1
    		set loc to location of aTrack as string
    		--		log "Loc " & loc
    		set theTextItems to text items of loc
    		--		try
    		set theTextItems to items 5 thru -1 of theTextItems -- wipe the path prefix
    		set newLoc to (theTextItems as string)
    		--			log "New Loc " & newLoc
    		
    		set Idx to my BinarySearch(newLoc, myList)
    		if Idx < 0 then
    			set Idx to -Idx
    			set iLoc to item Idx of myList
    			set nErr to nErr + 1
    			log "Not Found :" & "Idx " & Idx & " " & nErr
    			log newLoc
    			log iLoc
    		end if
    		--		on error
    		--			log "Error:" & loc
    		--		end try
    	end repeat
    	log "Errors : " & nErr
    end tell
    The binary search would use a case sensitive string comparison and when a match fails I was going to set the iTunes loc to the actual path of the song.
    This code is not final as my binary search routine fails as the list is not sorted correctly.

    I did mean find in all cases, sorry for the confusion.
    So now I will try to find a sort routine to sort my list of 88,000 odd strings. One or two I've tried simply crash with no meaningful error code. I'll keep looking and keep you posted.
    Once again Thanks
    Jon
     
  6. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #6
    If you know how to write binary search, you can write a binary insertion sort. This is an insertion sort, so the list is kept sorted and new items are inserted one by one. New additions start by doing a binary search. This identifies the index (position) where the item would be found if it were already inserted. That means it's also the index where the item should be inserted. Insert the item at that index, moving up all others, and the list now contains the new item at its correctly sorted location.
     
  7. Jon Trepte thread starter macrumors newbie

    Joined:
    Sep 17, 2014
    #7
    Fixed it!!

    Dear chown33,
    Right I've fixed my library at last. As you may know I was trying to copy my iTunes library from an external USB(Apple) drive to my NAS(linux). What I did initially was to simply copy the iTunes folder from "Volumes/Music&Pics/iTunes/..." to "Volumes/music/iTunes/..." where music is a public mounded volume on my Synology NAS. Next I pointed iTunes to this new library and all seemed OK until I tried to play a few songs and got the message that the file could not be found. So I wrote an AppleScript program to list all the file locations iniTunes and save them to a file (88,000 tracks). It took a while!!
    Went I opened the file i found that many of the tracks were still in the original location (5,00- or so) but most seemed to have been corrected by iTunes to point to the new location i.e. "Volumes/music/iTunes/iTunes Media/Music/..." but the bat tracks still had "Volumes/Music&Pics/iTunes/iTunes Media/Music/...". Im sure this had something to do with the fact that the NAS was case-sensitive but the USB drive was not. So I wrote the following code to try and fix the problem

    Code:
    tell application "iTunes"
    	activate
    	set AppleScript's text item delimiters to ":"
    	set fixed indexing to true
    	
    	set nCount to count tracks of playlist 1
    	log nCount
    	set nBad to 0
    	
    	repeat with i from 1 to nCount
    		set aTrack to track i of playlist 1
    		set loc to location of aTrack as string
    		if loc starts with "Music&Pics:" then
    			log i & " " & loc
    			
    			set theTextItems to text items of loc
    			set item 1 of theTextItems to "music"
    			set loc to (theTextItems as string) as alias
    			set location of aTrack to loc
    			
    			set nBad to nBad + 1
    		end if
    		if loc does not start with "music:" then -- double check
    			log i & loc
    		end if
    	end repeat
    	log nBad
    end tell
    
    
    It took a while but it seemed to fix the problems. I'm still not sure how iTunes fixed the case problems. This code is not quite right as it assumes the tracks start with "Music&Pics" (bad) or "music" (good). Anyway again many thanks for your help with this matter.
    Kindes regards
    Jon
     

Share This Page