Monday, September 1, 2014

#1 2005-12-28 08:31:29 am

Vincent
Member
From: Germany
Registered: 2004-04-06
Posts: 205

Challenge - How to get the parent path of a list of POSIX paths

Hi!

I'm wondering if anyone knows how to solve the following:

I've a list of POSIX paths (variable: listOfFiles)
Example:

this/is/a/test/path
this/is/another/test/path
this/is/a/taste/path
this/is/a/test/file
this/is/not/really/a/test/path

No I want to find out what parent path all these paths have in common!
(In this case "this/is/" would be the answer)

Applescript:


EqualParentPath({"this/is/a/test/path", "this/is/another/test/path", "this/is/a/taste/path", "this/is/a/test/file", "this/is/not/really/a/test/path"})
--Result: {"this/is/",8}

on EqualParentPath(listOfFiles)
   --script stuff comes here
   return {theEqualPath, lastEqualChar}
end EqualParentPath

Model: iBook G4
AppleScript: 1.10.3
Browser: Safari 412.5
Operating System: Mac OS X (10.4)

Offline

 

#2 2005-12-28 08:43:41 am

Joseph Briggs
Member
Registered: 2003-01-23
Posts: 122

Re: Challenge - How to get the parent path of a list of POSIX paths

I have a commonParent handler that deals with AppleScript paths that I'm sure you could modify to suit your needs.

Applescript:

on commonParent(theseFiles)
   if theseFiles is not {} then
       set startupDisk to characters 1 thru -2 of (path to startup disk as text) as text
       set fList to {}
       repeat with thisFile in theseFiles
           set end of fList to textToList(thisFile as text, ":")
       end repeat
       
       set lastCommonParent to {} -- a list to get all common parent path components
       set shouldRecordParent to true
       try
           set baseCompare to item 1 of fList
           repeat with i from 1 to count of baseCompare
               set thisParentItem to item i of baseCompare
               repeat with j from 2 to count of fList
                   set subCompareItem to item i of item j of fList
                   if subCompareItem is not equal to thisParentItem then
                       set shouldRecordParent to false
                   end if
               end repeat
               if shouldRecordParent then set end of lastCommonParent to thisParentItem
           end repeat
           
           if startupDisk is in lastCommonParent and (count of lastCommonParent) is 1 then
               -- the common parent is the startup disk
               -- disallow
               log "EXCEPTION@commonParent() : Common parent is the startup disk."
               return "Common parent is the startup disk."
           else
               set commonParentPath to listToText(lastCommonParent, ":") & ":" as alias
           end if
       on error e
           return e
       end try
   else
       return missing value
   end if
end commonParent

on textToList(thisText, delim)
   set {tid, my text item delimiters} to {my text item delimiters, delim}
   try
       set textList to every text item of thisText
       set my text item delimiters to tid
   on error
       set my text item delimiters to tid
   end try
   return textList
end textToList

on listToText(thisList, delim)
   set {tid, my text item delimiters} to {my text item delimiters, delim}
   try
       set textList to every item of thisList as text
       set my text item delimiters to tid
   on error
       set my text item delimiters to tid
       return e
   end try
   return textList
end listToText

Offline

 

#3 2005-12-28 08:48:35 am

Vincent
Member
From: Germany
Registered: 2004-04-06
Posts: 205

Re: Challenge - How to get the parent path of a list of POSIX paths

Great! Thanx!
What a quick answer - 12 minutes!

I just had to replace the ":" tith "/" and removed the "as alias" stuff

Offline

 

#4 2005-12-28 10:06:40 am

Joseph Briggs
Member
Registered: 2003-01-23
Posts: 122

Re: Challenge - How to get the parent path of a list of POSIX paths

I figured it would be easy enough to modify. Glad it worked for you.

Offline

 

#5 2005-12-28 02:08:19 pm

Mikey-San
Member
Registered: 2005-07-13
Posts: 509

Re: Challenge - How to get the parent path of a list of POSIX paths

$ man dirname

You can likely utilize this command to help reduce some of the above code.

Last edited by Mikey-San (2005-12-28 02:12:01 pm)

Offline

 

#6 2005-12-28 10:07:19 pm

Joseph Briggs
Member
Registered: 2003-01-23
Posts: 122

Re: Challenge - How to get the parent path of a list of POSIX paths

I read the man page for dirname to see if I could figure how best to trim the code but I couldn't come up with anything - though I admit I'm not that clever. What I did notice was my sloppy return values, which led to spotting another major fix, which trimmed the main handler nicely. Here is the corrected main handler:

Applescript:

on commonParent(theseFiles)
   set fList to {}
   repeat with thisFile in theseFiles
       set end of fList to textToList(thisFile as text, "/")
   end repeat
   
   set lastCommonParent to {} -- a list to get all common parent path components
   set shouldRecordParent to true
   try
       set baseCompare to item 1 of fList
       repeat with i from 1 to count of baseCompare
           set thisParentItem to item i of baseCompare
           repeat with j from 2 to count of fList
               set subCompareItem to item i of item j of fList
               if subCompareItem is not equal to thisParentItem then set shouldRecordParent to false
           end repeat
           if shouldRecordParent then set end of lastCommonParent to thisParentItem
       end repeat
   end try
   return listToText(lastCommonParent, "/") & "/"
end commonParent

Last edited by Joseph Briggs (2005-12-28 10:09:56 pm)

Offline

 

#7 2005-12-28 10:47:11 pm

ChrisAdmin
Member
From: Framingham, Ma
Registered: 2004-02-04
Posts: 133

Re: Challenge - How to get the parent path of a list of POSIX paths

I didn't read throught the whole script - but I just wanted to elaborate on what Mikey_san was saying..

dirname and basename are 2 unix utilities that I use a ton - and they are much easier than the Applescript way of doing it.  eg:

Applescript:

dirname /this/is/the/path/i_am_th_file.txt
--returns:
/this/is/the/path

basename /this/is/the/path/i_am_th_file.txt
--returns
i_am_th_file.txt

just thought you might find that interesting...

Offline

 

#8 2005-12-29 07:12:59 am

Joseph Briggs
Member
Registered: 2003-01-23
Posts: 122

Re: Challenge - How to get the parent path of a list of POSIX paths

Even though I'm still not seeing how I could use dirname in a more efficient algorithm, this is helping me a lot. It would be nice to know if I'm just overlooking something obvious, which has been known to happen.

Anyway, I made a few more tiny modifications to eliminate the listToText handler and the unecessary first loop, and accommodate either standard paths or POSIX paths.

Applescript:

on commonParent(theseFiles)
   set delim to ":"
   if item 1 of theseFiles as text does not contain ":" then set delim to "/"
   set lastCommonParent to {} -- a list to get all common parent path components
   set shouldRecordParent to true
   try
       set baseCompare to textToList(item 1 of theseFiles as text, delim)
       repeat with i from 1 to count of baseCompare
           set thisParentItem to item i of baseCompare
           repeat with j from 2 to count of theseFiles
               if item i of textToList(item j of theseFiles as text, delim) is not equal to thisParentItem then set shouldRecordParent to false
           end repeat
           if shouldRecordParent then set end of lastCommonParent to thisParentItem & delim
       end repeat
   end try
   if delim is "/" then return lastCommonParent as text
   return lastCommonParent as text as alias
end commonParent

on textToList(thisText, delim)
   set {tid, my text item delimiters} to {my text item delimiters, delim}
   try
       set textList to every text item of thisText
       set my text item delimiters to tid
   on error
       set my text item delimiters to tid
   end try
   return textList
end textToList

Offline

 

#9 2005-12-29 08:55:52 am

Vincent
Member
From: Germany
Registered: 2004-04-06
Posts: 205

Re: Challenge - How to get the parent path of a list of POSIX paths

Joseph, I now wrote one by myself.
(I just didn't know how to go about doing this when I posted my question)

I wrote my own routine which is about 3x faster than your last one:

Applescript:

on commonParent(fileList)
   set delim to ":"
   if item 1 of fileList contains "/" then set delim to "/"
   set {tid, my text item delimiters} to {my text item delimiters, delim}
   set PathToCompare to text items of (item 1 of fileList as text)
   set compareUntil to (count PathToCompare)
   repeat with i from 2 to count fileList
       set comparsionPath to text items of (item i of fileList as text)
       repeat with j from 1 to compareUntil
           if (item j of PathToCompare) = (item j of comparsionPath) then
           else
               --this line:
               set compareUntil to j - 1
               --and this line prevent the handler from wasting extra time n very long paths when difference was found somewhere at the beginning
               exit repeat
           end if
       end repeat
   end repeat
   try
       set common to (items 1 thru compareUntil of PathToCompare) as text
       set my text item delimiters to tid
   on error
       set my text item delimiters to tid
   end try
   return common
end commonParent

I have some things in mind that could still improve it - I'll post a optimized version when I've checked it.

-Vincent

Offline

 

#10 2005-12-29 08:57:58 am

Nigel Garvey
Moderator
From: Warwickshire, England
Registered: 2002-11-19
Posts: 3506

Re: Challenge - How to get the parent path of a list of POSIX paths

Hi. If you're interested, here's another approach that doesn't require nested repeats:

Applescript:

on EqualParentPath(listOfFiles)
   set astid to AppleScript's text item delimiters
   
   -- It's assumed here that the paths are POSIX paths.
   -- Combine the paths into a single text, each path beginning with a 'return' marker.
   set AppleScript's text item delimiters to return
   set listtext to (return as Unicode text) & listOfFiles
   
   -- Use the first return-marked path as a test source.
   set path1 to (return as Unicode text) & item 1 of listOfFiles
   -- Count the paths.
   set pathCount to (count listOfFiles)
   
   -- Set the TIDs to progressively longer sections of the first path.
   -- If there are more text items in the combined text than there are paths, all the paths contain the TIDs value.
   -- Otherwise, at least one of the paths does not match. The previous TIDs value is then what we want.
   set theEqualPath to "" -- In case there are no matches at all.
   set AppleScript's text item delimiters to "/"
   repeat with i from 1 to (count path1's text items)
       set AppleScript's text item delimiters to "/"
       set AppleScript's text item delimiters to (text 1 thru text item i of path1) & "/"
       if (count listtext's text items) > pathCount then
           set theEqualPath to AppleScript's text item delimiters
       else
           exit repeat
       end if
   end repeat
   set AppleScript's text item delimiters to astid
   
   -- Lose the leading return from the result
   if ((count theEqualPath) > 0) then set theEqualPath to text 2 thru -1 of theEqualPath
   
   return {theEqualPath, (count theEqualPath)}
end EqualParentPath

EqualParentPath({"this/is/a/test/path", "this/is/another/test/path", "this/is/a/taste/path", "this/is/a/test/file", "this/is/not/really/a/test/path"})
--Result: {"this/is/",8}


NG

Offline

 

#11 2005-12-29 10:01:11 am

Vincent
Member
From: Germany
Registered: 2004-04-06
Posts: 205

Re: Challenge - How to get the parent path of a list of POSIX paths

Nigel, I think we've (or better "you've") found the best way to do it!

I chacked them all with fila paths like this one:

this/is/a/very/long/and/silly/but/not/stupid/file/path/which/makes/no/sense/than/being/a/dummy/file/path/for/testing/this/particular/handler

your method is the only smart one! The other methods do too much checking than needed if the paths differ somewhere near the beginning.
And it is the fastest one! (I replaced the "as Unicode text" with "as text" to have a fair comparison)
It's even 3x faster than mine! And therefore 10x faster than the one before.

Thank you all(!) for these great code snippets! It's you who make Macscripter such a great place!

Last edited by Vincent (2005-12-29 10:03:06 am)

Offline

 

#12 2005-12-29 10:30:36 am

Joseph Briggs
Member
Registered: 2003-01-23
Posts: 122

Re: Challenge - How to get the parent path of a list of POSIX paths

Yeah, thanks Nigel.

Offline

 

#13 2005-12-29 11:24:22 am

Joseph Briggs
Member
Registered: 2003-01-23
Posts: 122

Re: Challenge - How to get the parent path of a list of POSIX paths

One problem for me, Nigel's handler doesn't handle a list of Finder aliases sad. But Vincent's does. Getting the index of the last common component and the exit repeat is just what I was looking for for that handler. Thanks.

Two notes about your script, Vincent:

Applescript:

if item 1 of fileList contains "/" then set delim to "/"

Mac file names can contain "/" but can't contain ":" which is why I test the other way.

Applescript:

set common to (items 1 thru compareUntil of PathToCompare) as text

For a standard path, this would also need the trailing ":". I know POSIX paths don't require the trailing "/" but having it doesn't effect the reference either so the line should have the " & delim" at the end to be safe.

Anyway, any advice on how to accommodate aliases with your method, Nigel?

Offline

 

#14 2005-12-29 04:47:51 pm

Nigel Garvey
Moderator
From: Warwickshire, England
Registered: 2002-11-19
Posts: 3506

Re: Challenge - How to get the parent path of a list of POSIX paths

Joseph Briggs wrote:

Anyway, any advice on how to accommodate aliases with your method, Nigel?

Hi, Joseph. I think the version below is good for aliases, file specifications, Mac OS paths, and POSIX paths, but not for Finder or System Events references. It assumes that all the items in the list are of the same type. (You may want to develop the input check at the top to ensure that they are.) It returns a POSIX path if the list contains POSIX paths, and a Mac OS path otherwise.

You noted that Mac OS file names can contain "/", but the POSIX paths of those same files will contain ":" instead! So I've used the expedient of trying to coerce one of the paths to file specification. If it works, the action is for Mac OS paths; otherwise it's assumed they're POSIX paths.

Applescript:

on EqualParentPath(listOfFiles)
   -- This input check needs to be more fully developed.
   if not ((class of listOfFiles is list) and ((count listOfFiles) > 0) and (class of item 1 of listOfFiles is in {alias, file specification, string, Unicode text})) then
       error
   end if
   
   set astid to AppleScript's text item delimiters
   
   -- It's assumed here that the list items are all the same type and are
   -- POSIX paths, HFS paths, aliases, or file specifications.
   -- Coerce the list to a single text, each item beginning with a 'return' marker.
   set AppleScript's text item delimiters to return
   set listText to (return as Unicode text) & listOfFiles
   
   -- Use the first return-marked item (path) as a test source.
   set path1 to text 1 thru text item 2 of listText
   -- If it can be coerced to file specification, its a Mac OS path. Otherwise assume it's a POSIX path.
   try
       (text item 2 of path1) as file specification
       set pathDelim to ":"
   on error
       set pathDelim to "/"
   end try
   -- Count the paths.
   set pathCount to (count listOfFiles)
   
   -- Set the TIDs to progressively longer sections of the first path.
   -- If there are more text items in the combined text than there are paths, all the paths contain the TIDs value.
   -- Otherwise, at least one of the paths does not match. The previous TIDs value is then what we want.
   set theEqualPath to "" -- In case there are no matches at all.
   set AppleScript's text item delimiters to pathDelim
   repeat with i from 1 to (count path1's text items)
       set AppleScript's text item delimiters to pathDelim
       set AppleScript's text item delimiters to (text 1 thru text item i of path1) & pathDelim
       if ((count listText's text items) > pathCount) then
           set theEqualPath to AppleScript's text item delimiters
       else
           exit repeat
       end if
   end repeat
   set AppleScript's text item delimiters to astid
   
   -- Lose the leading return from the result
   if ((count theEqualPath) > 0) then set theEqualPath to text 2 thru -1 of theEqualPath
   
   return {theEqualPath, (count theEqualPath)}
end EqualParentPath


NG

Offline

 

#15 2005-12-29 05:10:38 pm

Vincent
Member
From: Germany
Registered: 2004-04-06
Posts: 205

Re: Challenge - How to get the parent path of a list of POSIX paths

Nigel Garvey wrote:

Joseph Briggs wrote:

Anyway, any advice on how to accommodate aliases with your method, Nigel?

You noted that Mac OS file names can contain "/", but the POSIX paths of those same files will contain ":" instead! So I've used the expedient of trying to coerce one of the paths to file specification. If it works, the action is for Mac OS paths; otherwise it's assumed they're POSIX paths.

You could check whether there are more "/" than ":" -> probably POSIX
and vice versa… -> probably alias
big_smilelol

Offline

 

#16 2005-12-29 07:09:50 pm

Vincent
Member
From: Germany
Registered: 2004-04-06
Posts: 205

Re: Challenge - How to get the parent path of a list of POSIX paths

I've never really understood why there is need for an optional alias path format:|
It only bring problems with it to have several formats!

Offline

 

#17 2005-12-30 06:11:03 am

Joseph Briggs
Member
Registered: 2003-01-23
Posts: 122

Re: Challenge - How to get the parent path of a list of POSIX paths

Nigel Garvey wrote:

You noted that Mac OS file names can contain "/", but the POSIX paths of those same files will contain ":" instead!

Good grief. I did not know that.

As far as the handler, I need it to work with Finder refs, too, it seems, so I think I'm sticking with Vincent's variation. Thanks, though.

Offline

 

Board footer

Powered by FluxBB

[ Generated in 0.064 seconds, 8 queries executed ]

RSS (new topics) RSS (active topics)