Hi,
A friend of mine has a Buffalo Terastation NAS and needs to store a directory structure on it. The problem is that the device does not support long names, so he’s looking at having to bulk rename multiple items. I can script bulk renaming of files, that’s fairly simple, however, when folders become involved is where I get a little stuck as I need to potentially rename a folder with a long name, which would then screw up the recursvice search as the folder I’m looking for won’t exist.
Does anyone have an existing script that will recurse through a dropped folder renaming any files and folders it finds whose name is over a specific number of characters to another specific length?
I think there are more problems here than you think. Consider:
If you simply truncate the names according to a simple scheme, that scheme will have to include a check that the truncated name does not already exist in the target folder as a result of a previous truncation.
You have to rename and move as you go along unless your friend’s machine can hold duplicates of all the files he wants to move, or he intends to rename all of his own files and folders before backing them up to the NAS.
See this Code Exchange hint for the rapid production of a directory structure. See the Finder’s “entire contents” for getting all the files and folders.
This is from this bbs, and I apologize to it’s author - I didn’t make a note.
to drill_down(a_folder)
tell application "Finder"
set file_list to files of a_folder
set folder_list to folders of a_folder
end tell
repeat with I in file_list
processDrilledDownFile(I)
-- relieve the script by handling the found files first,
-- before diving deeper into the recursion with the found folders,
-- as this will minimize occurences of a stack overflow
end repeat
repeat with I in folder_list
processDrilledDownFolder(I)
drill_down(I) -- diving into the recursion with the found folders here
end repeat
end drill_down
-- similar handler for Folders, or integrate the two
on processDrilledDownFile(a_file)
-- a_file is passed on to the processDrilledDownFile handler as a Finder file object
-- so it must be further processed starting from within a "tell application Finder" block
tell application "Finder"
-- do your file processing here
end tell
end processDrilledDownFile
drill_down(choose folder)
This could be prettier, but it’s a start. It doesn’t remove illegal characters, but does handle varying numbers of characters in extensions.
set theFile to (choose file without invisibles)
set fileName to name of (info for theFile)
set theExt to name extension of (info for theFile)
set nameLength to count of fileName
set extLength to count of theExt
set cutOff to (30 - extLength)--30 to account for the "."
if nameLength > 31 then set shortName to text 1 through cutOff of fileName & "." & theExt
The Finder itself apparently works recursively when getting the entire contents of a folder. Folders always appear in the returned list before any items they may contain. So working backwards through the list will only rename folders whose items have already been processed and no harm will be done to the process.
Here’s a script you can adapt to your own needs. It duplicates a user-chosen folder to the desktop and returns a list containing the paths to the (duplicate) folder and all the items in its hierarchy. It then works textually through the paths, looking for names with more than 31 characters. Any such names are truncated and the items to which they belong are renamed.
The renaming scheme here uses the first 15 characters of the name and the last 15 (including any extension) and joins them with an ellipsis character. I reckon that should reduce the risk of name clashes; but if there are any, the last two characters of the new base name of the current item are replaced with a two-digit number, which is incremented until no clash occurs.
on main()
set astid to AppleScript's text item delimiters
truncateNames(getPaths())
set AppleScript's text item delimiters to astid
showMessage("Done!", note)
end main
(* Duplicate a chosen folder to the desktop and get the paths to it and everything in it. *)
on getPaths()
set originalFolder to (choose folder)
tell application "Finder"
try
set dupFolder to (duplicate originalFolder to desktop)
on error msg number -15267
my showMessage("A folder with the same name already exists on the desktop.", stop)
error number -128
end try
set AppleScript's text item delimiters to return
set thePaths to paragraphs of ((entire contents of dupFolder) as Unicode text)
set beginning of thePaths to dupFolder as Unicode text
end tell
return thePaths
end getPaths
(* Get item names from a list of paths, truncate any that have more
than 31 characters, and rename the items to which they refer. *)
on truncateNames(thePaths)
set colon to ":" as Unicode text
set ellipsis to "." as Unicode text
set dot to "." as Unicode text
set AppleScript's text item delimiters to colon
considering case
repeat with i from (count thePaths) to 1 by -1
set thisPath to item i of thePaths
if ((count thisPath) > 0) then -- There's sometimes a blank item at the end of the list.
set thisname to text item -1 of thisPath
if ((count thisname) is 0) then set thisname to text item -2 of thisPath -- Folder or package path ending in ":".
if ((count thisname) > 31) then
set newName to text 1 thru 15 of thisname & ellipsis & text -15 thru -1 of thisname
set counter to 100
repeat -- until no name clashes to cause errors.
try
tell application "Finder" to set name of item thisPath to newName
exit repeat
on error
-- Make a new name with a two-digit number after the base name.
set counter to counter + 1
set numberInsert to text 2 thru 3 of (counter as Unicode text)
if (newName contains dot) then -- Names with extensions.
set AppleScript's text item delimiters to dot
set extnLen to (count text item -1 of newName) + 1
set newName to text 1 thru (29 - extnLen) of thisname & numberInsert & text -extnLen thru -1 of newName
set AppleScript's text item delimiters to colon
else -- Names without extensions.
set newName to text 1 thru 29 of newName & numberInsert
end if
end try
end repeat
end if
end if
end repeat
end considering
end truncateNames
on showMessage(msg, iconType)
beep
tell application (path to frontmost application as Unicode text)
display dialog msg buttons {"OK"} default button 1 with icon iconType
end tell
end showMessage
main()
I’ve just spent 2 weeks on the same problem… long names and long characters are not supported… I suspect that if your friend is trying to connect to the drive via afp:// he will have a limit of 30 characters… if he uses smb:// the character limit will be 255 and he should be fine…
Furthermore if he connects via ftp:// as admin with the program ‘Transmit’ to the folder he wishes to drop the data into… there is no restriction on illegal characters… I assume the same would be true of filename length. He would need to enable ftp sharing for the shared volume on the Terastation and then allow the relevant user or the admin account in the ‘Group Management’ to be allowed to access the shared volume because ftp doesn’t recognise group authentication only user level.