I require a script that will flatten a folder overwriting any files that are duplicate filenames. I have written one myself but seems to fall over with duplicate file names. If I could also ensure that the most recent file was kept that would also be a great help.
Steve
Hi Steve,
This script was written quickly so it has little error checking or thought to it. You can try to make it more efficient. It seems to work with the little testing I did.
-- This script deletes files with duplicate names
-- according to date modified from a chosen folder.
set the_folder to ¬
(choose folder with prompt "Choose a folder to remove duplicates:")
set file_refs to MakeFileList(the_folder)
set num_items to count file_refs
if num_items > 1 then
tell application "Finder"
set file_refs to (sort file_refs by name)
repeat with i from 2 to num_items
set j to i - 1
set ref_i to item i of file_refs
set ref_j to item j of file_refs
set name_i to name of ref_i
set name_j to name of ref_j
if name_i is name_j then
set mod_date_i to modification date of ref_i
set mod_date_j to modification date of ref_j
if mod_date_i > mod_date_j then
delete ref_j
else
delete ref_i
set item i of file_refs to ref_j
end if
end if
end repeat
end tell
end if
on MakeFileList(the_folder)
set file_list to {}
tell application "Finder"
set item_list to every item of the_folder
repeat with i in item_list
if file type of i is "fold" then
set file_list to file_list & MakeFileList(i) of me
else
set file_list to file_list & i
end if
end repeat
end tell
return file_list
end MakeFileList
gl, Kel.
: Hi Steve,
: This script was written quickly so it has little error checking or thought to
: it. You can try to make it more efficient. It seems to work with the
: little testing I did.
:
: – This script deletes files with duplicate names – according to date
: modified from a chosen folder. set the_folder to ¬ (choose
: folder with prompt “Choose a folder to remove duplicates:”) set
: file_refs to MakeFileList(the_folder) set num_items to count file_refs
: if num_items > 1 then tell application “Finder”
: set file_refs to (sort file_refs by name) repeat with i
: from 2 to num_items set j to i - 1 set ref_i
: to item i of file_refs set ref_j to item j of file_refs
: set name_i to name of ref_i set name_j to name
: of ref_j if name_i is name_j then set
: mod_date_i to modification date of ref_i set
: mod_date_j to modification date of ref_j if mod_date_i
: > mod_date_j then delete ref_j
: else delete ref_i
: set item i of file_refs to ref_j
: end if end if end repeat
: end tell end if on MakeFileList(the_folder) set file_list
: to {} tell application “Finder” set item_list to
: every item of the_folder repeat with i in item_list
: if file type of i is “fold” then set
: file_list to file_list & MakeFileList(i) of me else
: set file_list to file_list & i end if
: end repeat end tell return file_list end
: MakeFileList
Thanks for all this. Wiill give it a try and let you know how I get on.
Steve
: gl, Kel.
: Hi Steve,
: This script was written quickly so it has little error checking or thought to
: it. You can try to make it more efficient. It seems to work with the
: little testing I did.
Does this script take in account recursive folders, as what I am ultimately after is some code that will flatten the folder at the same time so from a group of nested folders it ends with a single folder containg all file elements with duplicates deleted.
Steve
:
: – This script deletes files with duplicate names – according to date
: modified from a chosen folder. set the_folder to ¬ (choose
: folder with prompt “Choose a folder to remove duplicates:”) set
: file_refs to MakeFileList(the_folder) set num_items to count file_refs
: if num_items > 1 then tell application “Finder”
: set file_refs to (sort file_refs by name) repeat with i
: from 2 to num_items set j to i - 1 set ref_i
: to item i of file_refs set ref_j to item j of file_refs
: set name_i to name of ref_i set name_j to name
: of ref_j if name_i is name_j then set
: mod_date_i to modification date of ref_i set
: mod_date_j to modification date of ref_j if mod_date_i
: > mod_date_j then delete ref_j
: else delete ref_i
: set item i of file_refs to ref_j
: end if end if end repeat
: end tell end if on MakeFileList(the_folder) set file_list
: to {} tell application “Finder” set item_list to
: every item of the_folder repeat with i in item_list
: if file type of i is “fold” then set
: file_list to file_list & MakeFileList(i) of me else
: set file_list to file_list & i end if
: end repeat end tell return file_list end
: MakeFileList
: gl, Kel.
Hi Steve,
Yes. You can only have duplicate names in sub-folders. However, it does not eliminate the sub-folders. I’m about to sleep now, but, a quick thought is that you can bring the file to the root level at the same time where you’re comparing 2 files and their names are not the same then you would bring file j to the root level. So you might look for the form:
if name_i is name_j then
-- whatever went here
else
-- move the file to root level
end if
Then, lastly, you would have to eliminate all folders of the_folder.
Later, Kel.
Also, you have to think about the last loop. If the last two items of the list have the same names then one will be deleted and the last item in the list will be left there without being moved. If the last two items have different names then the second to last will be moved, but, the last item will still be left. So, when you exit the repeat loop, you need to move the last item in the list to the root level. Then, eliminate all the sub-folders.
Later again, Kel.
Hi Steve,
Here’s the working script according to what you wanted:
-- This script deletes files with duplicate names
-- according to date modified from a chosen folder.
set the_folder to ¬
(choose folder with prompt "Choose a folder to remove duplicates:")
set file_refs to MakeFileList(the_folder)
set num_items to count file_refs
if num_items > 1 then
tell application "Finder"
set file_refs to (sort file_refs by name)
repeat with i from 2 to num_items
set j to i - 1
set ref_i to item i of file_refs
set ref_j to item j of file_refs
set name_i to name of ref_i
set name_j to name of ref_j
if name_i is name_j then
set mod_date_i to modification date of ref_i
set mod_date_j to modification date of ref_j
if mod_date_i > mod_date_j then
delete ref_j
else
delete ref_i
set item i of file_refs to ref_j
end if
else
move ref_j to the_folder
end if
end repeat
move last item of file_refs to the_folder
delete (every folder of the_folder)
end tell
end if
on MakeFileList(the_folder)
set file_list to {}
tell application "Finder"
set item_list to every item of the_folder
repeat with i in item_list
if file type of i is "fold" then
set file_list to file_list & MakeFileList(i) of me
else
set file_list to file_list & i
end if
end repeat
end tell
return file_list
end MakeFileList
You might try testing it on copies of the original folder first. The list of files could be huge so increase the script app’s memory. 4 Mb worked with a list of about 200 files and I don’t know how much more it would have worked with. Note that it doesn’t take into account case of the characters of names. If you want case then you can use the statements:
considering case
-- statements where case must be considered
end considering
Lastly, try to look through it and see how you can make it better and possibly faster although it seems to work.
gl and happy scripting, Kel.
Since, we’re deleting sub-folders at the end, you don’t have to delete files here:
if mod_date_i > mod_date_j then
delete ref_j
else
delete ref_i
set item i of file_refs to ref_j
end if
So, change these lines to:
if mod_date_i < mod_date_j then
set item i of file_refs to ref_j
end if
Have a good day.
Fixed some stuff.
-- This script deletes files with duplicate names
-- according to date modified from a chosen folder.
-- Also, moves the files to the root level of the folder
-- and deletes all sub-folders.
set the_folder to ¬
(choose folder with prompt "Choose a folder to remove duplicates:")
set file_refs to MakeFileList(the_folder)
set num_items to count file_refs
tell application "Finder"
if num_items > 0 then
set file_refs to (sort file_refs by name) as list
if num_items > 1 then
repeat with i from 2 to num_items
set j to i - 1
set ref_i to item i of file_refs
set ref_j to item j of file_refs
set name_i to name of ref_i
set name_j to name of ref_j
if name_i is name_j then
set mod_date_i to modification date of ref_i
set mod_date_j to modification date of ref_j
if mod_date_i > mod_date_j then
delete ref_j
else
delete ref_i
set item i of file_refs to ref_j
end if
else
move ref_j to the_folder
end if
end repeat
end if
move last item of file_refs to the_folder
end if
set subfolder_list to every folder of the_folder
if subfolder_list is not {} then
delete (every folder of the_folder)
end if
end tell
-- returns a list of all files within the folder and sub-folders
on MakeFileList(the_folder)
set file_list to {}
tell application "Finder"
set item_list to every item of the_folder
repeat with i in item_list
if file type of i is "fold" then
set file_list to file_list & MakeFileList(i) of me
else
set file_list to file_list & i
end if
end repeat
end tell
return file_list
end MakeFileList
gl, Kel.