Wednesday, November 20, 2019

#1 2019-10-15 11:18:34 pm

daBee
Member
Registered: 2010-02-09
Posts: 110

Select Next Finder Item

Hi folks.

Is there a way to 'select next finder item' without having to build that list first?  I'm working with >5800 items and I want to just navigate from item to item down the sorted list by Name.  Is this possible? 

Example in pseudo-code:

set s to the selected item
loop 10 times
   copy selected item to target:folder:alpha
   select the next item in that finder window
/loop

It would make copying things over much easier, as the source is a Linux directory where it's Case-sensitive. 

Any insight on this would be appreciated.  It seems logical but challenging.

Cheers

Offline

 

#2 2019-10-16 10:47:12 pm

KniazidisR
Member
Registered: 2019-03-03
Posts: 720

Re: Select Next Finder Item

daBee wrote:

It seems logical but challenging.


This test shows that the items in the folder are returned in unsorted order:

Applescript:


tell application "Finder"
   set sourceFolder to target of Finder window 1
   return items of sourceFolder
end tell

HOWEVER, IF
1) the contents of the folder are already sorted by name in the order A-Z (but not vice versa),
2) you selected one of the folder elements in the window (as the starting point),


and you just need to go to the next element, then your task is solved successfully without re-sorting the contents in the code.

This becomes possible due to the fact that the Finder indexes the contents of the folder exactly in A-Z order. Therefore, you will be able to avoid re-sorting the contents in the code:

Applescript:


set destinationFolder to choose folder

tell application "Finder"
   set sourceFolder to target of Finder window 1
   set theItems to items of sourceFolder
   set aCounter to index of item 1 of (get selection) -- your selected in the folder item index
   repeat 10 times
       duplicate (item aCounter of theItems) to destinationFolder replacing yes
       -- other processing of an item
       set aCounter to aCounter + 1
   end repeat
end tell

Last edited by KniazidisR (2019-10-17 04:06:03 am)


Model: MacBook Pro
macOS Mojave -- version 10.14.4
Safari -- version 12.1
Firefox -- version 70.0

Offline

 

#3 2019-10-17 06:40:39 am

Nigel Garvey
Moderator
From:: Warwickshire, England
Registered: 2002-11-20
Posts: 5105

Re: Select Next Finder Item

KniazidisR wrote:

This becomes possible due to the fact that the Finder indexes the contents of the folder exactly in A-Z order.


Unfortunately, while that's true (in Mojave anyway), the indexing order is stricter than in a Finder sort-by-name. Case isn't ignored and numeric strings are treated lexically, not numerically.  sad  But it takes the Finder quite a while to sort over 5800 items by name, so it may be preferable to use ASObjC methods to get and sort them.

If for any reason daBee still wants the individual items to be selected while they're being copied, the Finder's select command will do the job. An alternative might be to move the selection down an item at a time with down-arrow keystrokes, but it might be a fussy job keeping these in sync with the duplicating.

Applescript:

use AppleScript version "2.5" -- El Capitan (10.11) or later
use framework "Foundation"
use scripting additions

main()

on main()
   tell application "Finder"
       activate
       set theFolder to target of front Finder window as alias
       set theSelection to selection
   end tell
   
   set fileManager to current application's class "NSFileManager"'s defaultManager()
   set theURLs to fileManager's contentsOfDirectoryAtURL:(theFolder) includingPropertiesForKeys:({}) options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value)
   set sortDescriptor to current application's class "NSSortDescriptor"'s sortDescriptorWithKey:("path") ascending:(true) selector:("localizedStandardCompare:") -- Specifies an ascending Finder-style sort of the URLs' paths.
   set sortedURLs to theURLs's sortedArrayUsingDescriptors:({sortDescriptor})
   
   if theSelection is {} then
       set aCounter to 1
   else
       set aCounter to (sortedURLs's indexOfObject:(theSelection as alias)) + 1
   end if
   
   script o
       property theItems : sortedURLs as list -- Long list of AS 'file' specifiers.
   end script
   
   repeat with i from aCounter to (count o's theItems)
       set thisItem to item i of o's theItems as alias
       tell application "Finder"
           select thisItem
           
           -- Duplication code here. Or use an ASObjC method (but not in this tell statement).
           
       end tell
   end repeat
end main


NG

Offline

 

#4 2019-10-17 10:33:11 am

daBee
Member
Registered: 2010-02-09
Posts: 110

Re: Select Next Finder Item

KniazidisR wrote:
daBee wrote:

It seems logical but challenging.



HOWEVER, IF
1) the contents of the folder are already sorted by name in the order A-Z (but not vice versa),
2) you selected one of the folder elements in the window (as the starting point),



Ok, let me reframe what I would like to do, as you've touched on something important.

I'm copying over a LAN from a linux box to my workstation.  I encounter errors when "Alpha Something" and "alpha something" folder names, which are completely legit on a Linux box, are not on my workstation.  Case-sensitivity kills the copy. 

rsync is slow and even with a generated report of what isn't copied, it's tough to troubleshoot and the mounted NAS device sometimes goes deaf.  That's another forum/thread in itself. 

So, I thought AS would be able to essentially step down the list and attempt to copy the directory over, even if it means replacing it.  That automation over a day or two would save me a lot of time.  Any errors, I could shove in a rescue block that could log to a file for manual attention. 

I'd like to have the ability to choose item #300 (sorted by Name) and run the script from there.  I don't need to start fresh again.  299 items have already been covered. 

Any ideas?

Offline

 

#5 2019-10-17 10:39:48 am

daBee
Member
Registered: 2010-02-09
Posts: 110

Re: Select Next Finder Item

KniazidisR wrote:
daBee wrote:

It seems logical but challenging.


This test shows that the items in the folder are returned in unsorted order:

Applescript:


tell application "Finder"
   set sourceFolder to target of Finder window 1
   return items of sourceFolder
end tell



That timed out, BTW.  5900 directories over a splotchy Gigabit Ethernet.

Offline

 

#6 2019-10-17 09:48:46 pm

KniazidisR
Member
Registered: 2019-03-03
Posts: 720

Re: Select Next Finder Item

daBee wrote:

I'd like to have the ability to choose item #300 (sorted by Name) and run the script from there.  I don't need to start fresh again.  299 items have already been covered. 

Any ideas?


I draw your attention to this: item 1 of (get selection) in my script is the same 300th item from which you want to start.

But as Nigel Garvey pointed out, Finder indexing doesn't exactly match sorting by item name. Therefore, my script may give you an inaccurate result.

I don’t know if this is OK for you: you select from 5900 files a certain sequence of files (say, 50 items. Manual, in the window). Then you run this script:

Applescript:


set destinationFolder to choose folder

tell application "Finder"
   set theItems to (get selection)
   repeat with anItem in theItems
       duplicate anItem to destinationFolder replacing yes
   end repeat
end tell

Last edited by KniazidisR (2019-10-17 10:03:19 pm)


Model: MacBook Pro
macOS Mojave -- version 10.14.4
Safari -- version 12.1
Firefox -- version 70.0

Offline

 

#7 2019-10-18 06:05:36 am

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6036

Re: Select Next Finder Item

daBee wrote:

I'm copying over a LAN from a linux box to my workstation.  I encounter errors when "Alpha Something" and "alpha something" folder names, which are completely legit on a Linux box, are not on my workstation.  Case-sensitivity kills the copy.



You could try something like this:

Applescript:

use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use scripting additions

set sourceFolder to POSIX path of (choose folder with prompt "Choose the remote folder")
set destFolder to POSIX path of (choose folder with prompt "Choose the local folder")
set fileManager to current application's NSFileManager's defaultManager()
set sourceFolder to current application's NSString's stringWithString:sourceFolder
set destFolder to current application's NSString's stringWithString:destFolder
-- get filenames and make lowercase equivalents
set sourceNames to fileManager's contentsOfDirectoryAtPath:sourceFolder |error|:(missing value)
set lowerNames to sourceNames's valueForKey:"lowercaseString"
-- make unique counted set
set dupeSet to current application's NSCountedSet's setWithArray:lowerNames
-- make duplicate of set but uncounted
set temp to current application's NSSet's setWithSet:dupeSet
-- subtract temp from dupeset so only items that were added more than once remain
dupeSet's minusSet:temp
-- use set to build list of actual duplicate names
set dupeArray to dupeSet's allObjects()
set dupes to {}
repeat with aDupe in dupeArray
   set theFilter to (current application's NSPredicate's predicateWithFormat:"SELF ==[c] %@" argumentArray:{aDupe})
   set theMatches to (sourceNames's filteredArrayUsingPredicate:theFilter)
   repeat with aName in theMatches
       set end of dupes to aName as text
   end repeat
end repeat
-- loop through copying
set failures to {} -- holds list of names where errors happen
repeat with i from 1 to count of sourceNames
   if (dupeSet's containsObject:(item i of lowerNames)) as boolean then
       -- try, and ignore error
       (fileManager's copyItemAtPath:(sourceFolder's stringByAppendingPathComponent:(item i of sourceNames)) toPath:(destFolder's stringByAppendingPathComponent:(item i of sourceNames)) |error|:(missing value))
   else
       set {theResult, theError} to (fileManager's copyItemAtPath:(sourceFolder's stringByAppendingPathComponent:(item i of sourceNames)) toPath:(destFolder's stringByAppendingPathComponent:(item i of sourceNames)) |error|:(reference))
       if theResult as boolean is false then
           set end of failures to (item i of sourceNames) as text
       end if
   end if
end repeat
-- show the results
set {saveTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {", "}}
set dupeString to dupes as text
set failureString to failures as text
set AppleScript's text item delimiters to saveTID
display dialog "Copying finished with:" & linefeed & "Failures: " & failureString & linefeed & linefeed & "Duplicates: " & dupeString

Last edited by Shane Stanley (2019-10-25 04:44:34 pm)


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#8 2019-10-21 08:53:14 am

daBee
Member
Registered: 2010-02-09
Posts: 110

Re: Select Next Finder Item

Thanks for the post.  The job was done manually (many 'duplicates').  But I will take a look and fidget with Finder selections.

Cheers

Offline

 

#9 2019-10-24 03:19:29 pm

peavine
Member
From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 219

Re: Select Next Finder Item

Nigel Garvey wrote:

Unfortunately, while that's true (in Mojave anyway), the indexing order is stricter than in a Finder sort-by-name. Case isn't ignored and numeric strings are treated lexically, not numerically.



I always learn a lot by checking Nigel's work and so I put his above statement to the test. I created six files in a folder, and the name-sorted Finder window showed the following:

File 1
file 2
File 3
file 4
File 20
file 30

I ran the following script:

Applescript:

tell application "Finder"
   set theFiles to every file in folder theFolder
end tell

And, as Nigel predicted, this returned the files in the following order:

File 1
File 20
File 3
file 2
file 30
file 4

Last edited by peavine (2019-10-24 07:06:02 pm)


2018 Mac mini - macOS Mojave

Offline

 

#10 2019-10-24 05:07:37 pm

daBee
Member
Registered: 2010-02-09
Posts: 110

Re: Select Next Finder Item

That's 6 items.  Now try 5900.  It will time out. 

So then it means taking this to Ruby and breaking up the copies per individual directory, coupled with the same recursive challenge of changing the directory name with a suffix, or something like that.

Offline

 

#11 2019-10-25 10:14:07 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 3635

Re: Select Next Finder Item

Here I correct a typo in Shane's proposal and add some instructions to sort as the Finder does.

Applescript:

(*
Beginning of the original code
*)

       if theResult as boolean is false then
           set end of failures to (item i of sourceNames) as text # WAS theFailures
       end if
   end if
end repeat
-- show the results
set {saveTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {", "}}
set dupeString to (my sortAList:dupes) as text
set failureString to (my sortAList:failures) as text
set AppleScript's text item delimiters to saveTID
display dialog "Copying finished with:" & linefeed & "Failures: " & failureString & linefeed & linefeed & "Duplicates: " & dupeString


on sortAList:theList
   set theArray to current application's NSArray's arrayWithArray:theList
   set theArray to theArray's sortedArrayUsingSelector:"localizedStandardCompare:"
   return theArray as list
end sortAList:

With the typo corrected, the original returned:
"Copying finished with:
Failures: File 1, File 11, File 16, File 21, File 26, File 31, File 36, File 41, File 46, File 51, File 56, File 6, File 61, File 66, File 71, File 76, File 81, File 86, File 91, File 96

the edited version return:
"Copying finished with:
Failures: File 1, File 6, File 11, File 16, File 21, File 26, File 31, File 36, File 41, File 46, File 51, File 56, File 61, File 66, File 71, File 76, File 81, File 86, File 91, File 96"

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 25 octobre 2019  18:17:59

Last edited by Yvan Koenig (2019-10-25 10:18:05 am)

Offline

 

#12 2019-10-25 04:45:15 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6036

Re: Select Next Finder Item

Yvan Koenig wrote:

Here I correct a typo in Shane's proposal



Thank you, Yvan. I've made the correction above.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)