Record folder name and date modified.... please help!

Hi all,

Firstly, I should point out that I am very new to this and hoped I might get some help here.

I’m trying to generate a text file that records the name and date modified properties of all folders on an SMB file server.
I managed this:

tell application “Finder”
activate
set _folder to POSIX path of ((folder of the front window) as alias)
set _files to (get selection)
set _file to item 1 of _files
set _name to (name of _file)
set _date to (creation date of _file)
set {year:y, month:m, day:d, hours:h, minutes:m} to _date
set the clipboard to (_name & " " & _date)
end tell

However that only records them one by one and I’d like my script to copy this information in one go so I can paste into txt edit, Is this possible?

Many thanks in advance.

Scott:o

You write you want to get name and date modified of all folders of a file server.

Your script gets name and creation date of the first item (file or folder) of the selected items.

What is correct? And what does all folders mean? The folders of the current folder or a shallow enumeration including all descendants?

Hey Stefan,

Sorry, I see what you mean… Yes, the script gets the name and creation/modified date of the first item (file or folder)
but not folders contained within.

Hope this makes sense.

Scott

So you want to make it rescursive?

Isn’t find and stat in the shell easier?

set theFolder to quoted form of posix path of (choose folder)
do shell script "find " & theFolder & " -maxdepth 1 -type d -exec stat -f '%Sm%t%Sc%t%N' -t '%Y-%m-%d %H:%m:%S' {} + > $HOME/Desktop/Report.txt"

A file on your desktop name Report.txt is created after it is finished.

Wow thank you, not sure how you mean by recursive?

I have a work folder that contains 100s of job folders with a job number on each.
I just want to record the job number and date modified of the folder, but not what is contained in the folders.

I ran that script which works really well but records the folders contents.

Scott

I’ve updated the code above, it will now only list directories.

edit: Update 2 - it will not search deeper than 1 level.

Thank you very much, That works really well.

Cheers for your help.

Scott

Here is an alternate scheme with no limit for the deep of folders hierarchy.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions


on run
	my germaine()
end run

on germaine()
	set sourceFolder to POSIX path of (choose folder)
	
	set theFoldersInfos to my listFoldersIn:sourceFolder
	
	set theData to my recolle(theFoldersInfos, linefeed)
	
	set targetFile to POSIX path of ((path to desktop as text) & "myFiles_seliFym.txt")
	
	my writeToReport(targetFile, theData, «class utf8», false)
	
end germaine

on listFoldersIn:sourceFolder
	set dirKey to current application's NSURLIsDirectoryKey
	set packageKey to current application's NSURLIsPackageKey
	set fileManager to current application's NSFileManager's defaultManager()
	set aURL to current application's |NSURL|'s fileURLWithPath:sourceFolder
	
	set theOptions to (current application's NSDirectoryEnumerationSkipsPackageDescendants as integer) + (current application's NSDirectoryEnumerationSkipsHiddenFiles as integer)
	set theEnumerator to fileManager's enumeratorAtURL:aURL includingPropertiesForKeys:{} options:theOptions errorHandler:(missing value)
	set theList to {"modification dates" & tab & "folders paths"}
	repeat with aURL in theEnumerator's allObjects()
		set isFile to true
		-- is it a directory?
		set {theResult, theValue, theError} to (aURL's getResourceValue:(reference) forKey:dirKey |error|:(reference))
		if theValue as boolean then
			-- is it a package?
			set {theResult, theValue, theError} to (aURL's getResourceValue:(reference) forKey:packageKey |error|:(reference))
			if not theValue as boolean then
				set isFile to false
			end if
		end if
		if not isFile then
			set {theResult, theModDate} to (aURL's getResourceValue:(reference) forKey:(current application's NSURLContentModificationDateKey) |error|:(missing value))
			set aDescriptor to ((theModDate's |description|()) as text) & tab & aURL's |path|() as text
			set end of theList to aDescriptor
		end if
	end repeat
	
	return theList
end listFoldersIn:

#=====#=====#=====#=====#=====#=====

on recolle(l, d)
	local oTIDs, t
	set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
	set t to l as text
	set AppleScript's text item delimiters to oTIDs
	return t
end recolle

#=====#=====#=====#=====#=====#=====
(*
Handler borrowed to Regulus6633 - http://macscripter.net/viewtopic.php?id=36861
*)
on writeToReport(targetFile, theData, dataType, apendData)
	-- theData is the data you want in the file.
	-- dataType is the data type of theData and it can be text, list, record etc.
	-- apendData is true to append theData to the end of the current contents of the file or false to overwrite it
	
	try
		set targetFile to targetFile as «class furl»
		set openFile to open for access targetFile with write permission
		if not apendData then set eof of openFile to 0
		write theData to openFile starting at eof as dataType
		close access openFile
		return true
	on error
		try
			close access targetFile
		end try
		return false
	end try
end writeToReport

#=====#=====#=====#=====#=====#=====

Yvan KOENIG running Sierra 10.12.5 in French (VALLAURIS, France) lundi 26 juin 2017 21:09:34

For the record: My command above can be adjusted by the -maxdepth value to any level you want or remove the parameter entirely if you don’t want a limit like Yvan’s script.

The disadvantage of DJ’s approach is that it will also treat any packages, such as applications, as directories. In the immediate use case that might not matter, but in other cases it can matter a lot.

If you only want to go one level deep, the listFoldersIn: handler in Yvan’s script can be made a bit more efficient like this:

on listFoldersIn:sourceFolder
	set dirKey to current application's NSURLIsDirectoryKey
	set packageKey to current application's NSURLIsPackageKey
	set fileManager to current application's NSFileManager's defaultManager()
	set aURL to current application's |NSURL|'s fileURLWithPath:sourceFolder
	
	set theURLs to fileManager's contentsOfDirectoryAtURL:aURL includingPropertiesForKeys:{dirKey, packageKey} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value)
	set theList to {"modification dates" & tab & "folders paths"}
	repeat with aURL in theURLs
		set isFile to true
		-- is it a directory?
		set {theResult, theValue, theError} to (aURL's getResourceValue:(reference) forKey:dirKey |error|:(reference))
		if theValue as boolean then
			-- is it a package?
			set {theResult, theValue, theError} to (aURL's getResourceValue:(reference) forKey:packageKey |error|:(reference))
			if not theValue as boolean then
				set isFile to false
			end if
		end if
		if not isFile then
			set {theResult, theModDate} to (aURL's getResourceValue:(reference) forKey:(current application's NSURLContentModificationDateKey) |error|:(missing value))
			set aDescriptor to ((theModDate's |description|()) as text) & tab & aURL's |path|() as text
			set end of theList to aDescriptor
		end if
	end repeat
	
	return theList
end listFoldersIn:

And if you want the ability to specify how deep to look, you con do something like this:

on listFoldersIn:sourceFolder toLevel:levelNumber
	set dirKey to current application's NSURLIsDirectoryKey
	set packageKey to current application's NSURLIsPackageKey
	set fileManager to current application's NSFileManager's defaultManager()
	set aURL to current application's |NSURL|'s fileURLWithPath:sourceFolder
	
	set theOptions to (current application's NSDirectoryEnumerationSkipsPackageDescendants as integer) + (current application's NSDirectoryEnumerationSkipsHiddenFiles as integer)
	set theEnumerator to fileManager's enumeratorAtURL:aURL includingPropertiesForKeys:{dirKey, packageKey} options:theOptions errorHandler:(missing value)
	set theList to {"modification dates" & tab & "folders paths"}
	repeat
		set aURL to theEnumerator's nextObject()
		if aURL is missing value then exit repeat
		set isFile to true
		-- is it a directory?
		set {theResult, theValue, theError} to (aURL's getResourceValue:(reference) forKey:dirKey |error|:(reference))
		if theValue as boolean then
			-- is it a package?
			set {theResult, theValue, theError} to (aURL's getResourceValue:(reference) forKey:packageKey |error|:(reference))
			if not theValue as boolean then
				set isFile to false
			end if
		end if
		if not isFile then
			set {theResult, theModDate} to (aURL's getResourceValue:(reference) forKey:(current application's NSURLContentModificationDateKey) |error|:(missing value))
			set aDescriptor to ((theModDate's |description|()) as text) & tab & aURL's |path|() as text
			set end of theList to aDescriptor
			if theEnumerator's level() = levelNumber then theEnumerator's skipDescendants()
		end if
	end repeat
	
	return theList
end listFoldersIn:toLevel:

True, if that would be important you could use mdfind and xargs to do the same. I assumed it would not be important because of the SMB volume, so I went go for the much faster find command in this case.