-- Set fileList to those filenames whose lengths are greater than maxCount
script o
property filePaths : ""
property folderPaths : ""
end script
set o's filePaths to paragraphs of (do shell script "/usr/bin/find " & quoted form of FolderTarget & " -type f ! -type l ! -name '.*'")
set o's folderPaths to paragraphs of (do shell script "/usr/bin/find " & quoted form of FolderTarget & " -type d")
display dialog "Are the file pathname lengths being tested in HFS or POSIX file format?" buttons {"HFS", "POSIX"} default button 2 with icon note
set fileFormat to button returned of result
if fileFormat = "POSIX" then
repeat with aPath in o's filePaths
if (length of aPath) > maxCount then set end of fileList to contents of aPath -- as alias
end repeat
else
repeat with aPath in o's filePaths
set HFSPath to POSIX file (aPath as string) as string
if (length of HFSPath) > maxCount then set end of fileList to HFSPath -- as alias
end repeat
end if
The problem is as follows:
When I select “POSIX” the script runs perfectly.
When I select “HFS” I get the following error message:
Correct, I am calling this inside a Finder tell block.
The entire bit of code is:
tell application "Finder"
-- Define the list of files whose pathnames exceed maxCount characters
set fileList to {}
-- Define / set maxCount characters
display dialog "What is the maxCount of characters to test each filename's lenght against?
When entering a value make sure to adjust the value for the file formath [i.e. HFS vs POSIX] and the volume location / type [i.e. a Window's volume will have pathnames that start with \"C:\" in place of \"\\Volumes\" meaning that a value of 256 should be entered when wanting to test for a pathname length of 250 (i.e. 250 - 2 + 8)]." default answer "225" buttons {"Cancel", "Return"} default button 2 with icon note
set maxCount to text returned of result
-- Pick the disk / directory / folder (and sub-folders) whose files' pathnames will be compared / tested against maxCount
set FolderTarget to POSIX path of (choose folder with prompt "Choose the disk / directory / folder whose file lengths' will be compared against maxCount" default location (path to home folder))
set FolderTarget to characters 1 through -2 of FolderTarget as text -- remove the second "/" between the folder chosen and any nested folders
-- log "folderTarget"
-- log folderTarget
-- Create a dialog box to inform the user that the script is running
-- This is the code to be used when placing the dialog box inside of a tell block
set time1 to current date
set AppleScript's progress completed steps to 1
repeat with i from 2 to 10
set AppleScript's progress description to "Processing " & (i - 1) & " of " & 10
-- do shell script "sleep 0.5" -- Commented out as no need to list step number in bottom corner of dialog box
-- set AppleScript's progress completed steps to i -- Commented out as no need to list step number in bottom corner of dialog box
end repeat
-- display dialog ((current date) - time1) as text -- Commented out as no need for a dialog box that list number of seconds to complete the script
-- Set fileList to those filenames whose lengths are greater than maxCount
script o
property filePaths : ""
property folderPaths : ""
end script
set o's filePaths to paragraphs of (do shell script "/usr/bin/find " & quoted form of FolderTarget & " -type f ! -type l ! -name '.*'")
set o's folderPaths to paragraphs of (do shell script "/usr/bin/find " & quoted form of FolderTarget & " -type d")
display dialog "Are the file pathname lengths being tested in HFS or POSIX file format?" buttons {"HFS", "POSIX"} default button 2 with icon note
set fileFormat to button returned of result
if fileFormat = "POSIX" then
repeat with aPath in o's filePaths
if (length of aPath) > maxCount then set end of fileList to contents of aPath -- as alias
end repeat
else
repeat with aPath in o's filePaths
set HFSPath to POSIX file (aPath as string) as string
if (length of HFSPath) > maxCount then set end of fileList to HFSPath -- as alias
end repeat
end if
-- Set fileList to include the count/index, the file pathname's length and the file's pathname
repeat with i from 1 to count of fileList
set item i of fileList to {count of item i of fileList, item i of fileList}
end repeat
-- Sort fileList based on the files' pathname lengths from highest to lowest to highest
set callSortLocation to "Macintosh HD:Users:JoelC:Documents:Apple:Scripts:Utilities:20141125_script to sort a list of items_specific.scpt" as alias -- Set callSort to load a compiled sorting script
set callSort to (load script callSortLocation)
tell callSort -- Tell callSort to sort fileList
set fileList to simple_sort(fileList)
end tell
log "Total files are " & (count of o's filePaths)
log "Total folders are " & (count of o's folderPaths)
log "Total files and folders to compare to finder are " & ((count of o's filePaths) + (count of o's folderPaths) + 1) -- The 1 is for the parent folder
log "The fileList follows"
-- return fileList
end tell
What bit of code am I missing (as this script used to work, honest)?
Well don’t. The only code that should be within a tell block is code related to the target app. Apart from perhaps the dialog code (assuming you want the dialog to appear in the Finder), what has the rest of your script to do with the Finder? Nothing. So stop wasting the Finder’s time with code that’s none of its business.
Your code also fails to distinguish between folders and package files, and unfortunately traverses the contents of packages, too.
Apologies for my lack of experience but can you please elaborate on i) failing to distinguish between folders and package files and ii) traversing the contents of packages.
Packages are directories that look and behave like a single file. Apps are the most common, but there are plenty of others: .rtfd, .scpts, some of the older iWorks files, and so on. Shell tools like find work at the Unix level and don’t know anything about packages – as far as they are concerned, they are just directories. Hence they will end up in the wrong list, and find will also rifle through their contents.
That said, what is the best way for me to solve the problem in addition to limiting the scope of the Finder tell block noting I am still confused as to why this worked under Yosemite but no longer works under El Capitan.
The Finder problem is easy: just get rid of the Finder tell statement altogether. I’ve no idea what’s changed, but it doesn’t matter: directing all that stuff to the Finder is worse than pointless.
The problem with packages and folders is not so easily fixed. In theory you could use the Finder for that, but in practice it collapses with hierarchies of any reasonable size. If you know exactly which packages are likely to be found, you can tell find to ignore them, although that’s a bit icky.
You can try something like Satimage.osax’s list files command and its conforming to parameter, although last I looked there are issues with invisible files going that way. And then there’s AppleScriptObjC, which is more code and a bit slower than find, but will give you the correct results.
I’m also not sure why you need to convert all the POSIX paths to HFS paths for that choice. Unless the user chooses the root path, the relationship between the POSIX and HFS lengths will be fixed, so you can do that conversion just once.
This probably doesn’t do exactly what you want, but it should give you something to go on:
use AppleScript version "2.5" -- requires El Capitan or later
use scripting additions
use framework "Foundation"
-- Define / set maxCount characters
set theResult to (display dialog "What is the maxCount of characters to test each filename's length against?" default answer "225" buttons {"Cancel", "POSIX", "HFS"} with icon note)
set maxCount to (text returned of theResult) as integer
set fileFormat to button returned of theResult
set FolderTarget to (choose folder with prompt "Choose the disk / directory / folder whose file lengths' will be compared against maxCount" default location (path to home folder))
set hfsLength to length of (FolderTarget as text)
set folderPosix to POSIX path of FolderTarget
set posixLength to length of folderPosix
if fileFormat = "HFS" then set maxCount to maxCount + hfsLength - posixLength
-- make URL
set theNSURL to current application's class "NSURL"'s fileURLWithPath:folderPosix
-- make file manager
set theNSFileManager to current application's NSFileManager's new()
-- get URL enumerator
set theNSFileEnumerator to theNSFileManager's enumeratorAtURL:theNSURL includingPropertiesForKeys:{current application's NSURLPathKey, current application's NSURLIsDirectoryKey, current application's NSURLIsPackageKey} options:((current application's NSDirectoryEnumerationSkipsPackageDescendants) + (current application's NSDirectoryEnumerationSkipsHiddenFiles as integer)) errorHandler:(missing value)
-- get all items from enumerator
set allItems to theNSFileEnumerator's allObjects()
-- filter out those with long names
set thePred to current application's NSPredicate's predicateWithFormat_("path.length > %@", maxCount)
set longItems to allItems's filteredArrayUsingPredicate:thePred
-- set up variables
set folderList to current application's NSMutableArray's array()
set filesList to current application's NSMutableArray's array()
set longItemsCount to count of longItems
-- loop through
repeat with i from 1 to longItemsCount
-- is it a directory?
set {theResult, isDirectory} to ((item i of longItems)'s getResourceValue:(reference) forKey:(current application's NSURLIsDirectoryKey) |error|:(missing value))
if isDirectory as boolean then
set {theResult, isPackage} to ((item i of longItems)'s getResourceValue:(reference) forKey:(current application's NSURLIsPackageKey) |error|:(missing value))
-- is it a package?
if isPackage as boolean then
(filesList's addObject:(item i of longItems))
else
(folderList's addObject:(item i of longItems))
end if
else
(filesList's addObject:(item i of longItems))
end if
end repeat
-- sort arrays by path length
set sortDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"path.length" ascending:false
set folderList to folderList's sortedArrayUsingDescriptors:{sortDesc}
set filesList to filesList's sortedArrayUsingDescriptors:{sortDesc}
-- convert to lists of paths
if fileFormat = "HFS" then
set saveTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to {linefeed}
set theFiles to filesList as list as text -- this relies on bridging only available in El Capitan
set theFolders to folderList as list as text -- this relies on bridging only available in El Capitan
set AppleScript's text item delimiters to saveTID
else
set theFiles to ((filesList's valueForKey:"path")'s componentsJoinedByString:linefeed) as text
set theFolders to ((folderList's valueForKey:"path")'s componentsJoinedByString:linefeed) as text
end if
log "Total files and folders are " & (count of allItems)
log "Total files and folders to compare to finder are " & longItemsCount
log "The fileList follows"
log theFiles
log "The folderList follows"
log theFolders
It skips packages, but it still searches within them. And it’s going to skip any folders with a . in their name.
Things that mostly work are just bugs waiting to happen, IMO. If there were no other option, fine – but that’s not the case.
FWIW, Axel Luttgens posted a solution on Apple’s AppleScript mailing list a while back, and it works – as long as you include every extension used by a package. His script was:
set AppleScript's text item delimiters to {return}
set mylist to text items of (do shell script "/usr/bin/find -E " & myfolder & " -type d \\( \\( -iregex '.*\\.(xcodeproj|deps|nib|app|pbproj|fs|ppp|workflow|xcode|xcdatamodel|pkg|bundle|lpdf|kext|dSYM|wdgt|settings|trace|Patch|split)$' -and -prune \\) -or -print \\)")
As you can see, his list doesn’t include common ones like .scptd and .rtfd. And every time you use a new app that deals in packages, you have to edit the script.
I suppose I struggle to understand why someone would choose something that sort of works over something that works.
You certainly have valid points about find, especially regarding my suggestion still searching within package folders”ouch!” but there is rarely one thing that always works in every situation. My older Macs still can’t use ASOC. The shell is fast, tersely writ, and can generally be made to work, with a bit of futzing and testing. Thanks for also including Luttgens’ alternative method in your reply.
@ All, very strange result (at least me)…at Shane’s suggestion I got rid of the Finder block and voila, all was well in that the script is now working…I suppose that something changed between Yosemite and El Capitan that created this problem but in the end I am happy with the change because i) it works and ii) it is better form!
@ Shane, thanks not only for the help but also for the “alternate code”. It does, as you note, work but it is will take me a while to digest as it is far above my knowledge basis bit gives me something to work towards…thanks again!
Not really strange. Maybe some explanation will clear things out. The problem goes back to the first release of Mac OS X. AppleScript was always very forgiven until Mac OS X 10.5 were Apple started to recognize the security leaks in the OSA environment including AppleScript. In 10.5 they added that the system is registering events and no longer the scripting addition by itself. In 10.6 they started to add forgiven bounce backs, meaning that a do shell script command in an remote application like the Finder is silently given an error and is re-tried in the current application context. Mac OS X 10.6 started this all because scripting addition commands were given contextual restrictions. In Mac OS X 10.7 pre 10.5 scripting additions were no longer allowed to use. In 10.8 nothing really changes according to scripting additions apart from code signing which was an OS security not really a scripting addition only. In 10.9 the silently bounce backs were less silent and wrongly addressed commands from an scripting addition are in some situations actually thrown as an error.
Do shell script is such an scripting addition command. It’s not that this issue is El Capitan related but it’s Mac OS X 10.6 related.
@ DJ Bazzie, appreciate the history lesson and explanation, very helpful to someone like me. And yes, it is good to have this solved, somewhat explained and back to normal.
[quote=DJ Bazzie WazzieIt’s not that this issue is El Capitan related but it’s Mac OS X 10.6 related.
[/quote]
I’m not disagreeing, but the OP did say that his code was working in 10.10. He might have made some changes, but that does suggest a more recent change.
[/quote]
I’m not disagreeing, but the OP did say that his code was working in 10.10. He might have made some changes, but that does suggest a more recent change.
[/quote]
[/quote]
I did NOT make any changes between 10.10 and 10.11, not a one…it just stopped working for HFS file females within the Finder Tell Block…