Counting Files in a Folder

Here is a full version without dependence on local library paths and the use of run script etc:

use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

on run
    set fp to "~/Desktop/"
    
    script isRegular
        on |λ|(x)
            set lrStatus to fileStatus(filePath(fp & x))
            if |Left| of lrStatus is missing value then
                if "." is not first character of x and ¬
                    "NSFileTypeRegular" = NSFileType of |Right| of lrStatus then
                    {x}
                else
                    {}
                end if
            else
                {}
            end if
        end |λ|
    end script
    
    length of concatMap(isRegular, getDirectoryContents(fp))
end run

-- PASTED GENERICS ----------------------------------------------------

-- Left :: a -> Either a b
on |Left|(x)
    {type:"Either", |Left|:x, |Right|:missing value}
end |Left|

-- Right :: b -> Either a b
on |Right|(x)
    {type:"Either", |Left|:missing value, |Right|:x}
end |Right|

-- concatMap :: (a -> [b]) -> [a] -> [b]
on concatMap(f, xs)
    tell mReturn(f)
        set lng to length of xs
        set acc to {}
        repeat with i from 1 to lng
            set acc to acc & |λ|(item i of xs, i, xs)
        end repeat
    end tell
    return acc
end concatMap

-- filePath :: String -> FilePath
on filePath(s)
    ((current application's ¬
        NSString's stringWithString:s)'s ¬
        stringByStandardizingPath()) as string
end filePath

-- fileStatus :: FilePath -> Either String Dict
on fileStatus(fp)
    set e to reference
    set {v, e} to current application's NSFileManager's defaultManager's ¬
        attributesOfItemAtPath:fp |error|:e
    if v is not missing value then
        |Right|(v as record)
    else
        |Left|((localizedDescription of e) as string)
    end if
end fileStatus

-- getDirectoryContents :: FilePath -> IO [FilePath]
on getDirectoryContents(strPath)
    set ca to current application
    (ca's NSFileManager's defaultManager()'s ¬
        contentsOfDirectoryAtPath:(stringByStandardizingPath of ¬
            (ca's NSString's stringWithString:(strPath))) ¬
            |error|:(missing value)) as list
end getDirectoryContents

-- Lift 2nd class handler function into 1st class script wrapper 
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
    if class of f is script then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn

Is there anything wrong with doing it this way? It works for me.

1 Like

It's fine – it's just a bit slow for really big folders.

Untested, but I think it will also count folders -- if so, easily solved with a file attributes test.

2 Likes

Right... I figured as much as soon as I posted! But in my use case, it's not an issue.