So, after working with a side-project for about 6 hours today, pulling my hair because CSS makes absolutely no sense to me sometimes, I decided to improve on the Downloads Organizer
I made in Ruby the other week.
This is part two / version two. You can view the first article here: Organize Your Downloads Folder with Ruby
So what I added was a way of checking the type of the files, and also organizing them into their own subfolders. To achieve this I used regex
to the check the file-endings of the files.
After getting it to work, I had to refactor.. A LOT.. But here are the final results, a couple of functions doing bits and pieces I'll walk you through under the codeblock.
require 'find'
require 'fileutils'
downloads_folder = File.join(Dir.home, 'Downloads')
## Arrays used in the filtering logic.
yearly_folders = ["2019", "2020", "2021", "2022", "2023", "2024", "2025"]
def check_type(file)
case file
when /^.*\.(pdf|doc|docx|PAGES|txt)$/i
'documents'
when /^.*\.(gif|jpg|jpeg|png|svg|mp4|mov|mp3|mpeg4|heic)$/i
'media'
when /^.*\.(dmg|exe|jar)$/i
'programs'
when /^.*\.(zip|tar|rar)$/i
'archives'
else
'other'
end
end
def create_directory(directory, subfolder)
final_directory = File.join(directory, subfolder)
Dir.mkdir(final_directory) unless File.directory?(final_directory)
final_directory
end
def move_file(file, directory)
final_directory = create_directory(directory, check_type(file))
FileUtils.mv(file, final_directory) unless file === directory
end
def organize_downloads(downloads_folder, yearly_folders)
Dir.foreach(downloads_folder) do |file|
next if file == '.' || file == '..' || yearly_folders.include?(file)
path = File.join(downloads_folder, file)
next unless File.exist?(path)
last_edited = File.mtime(path)
year = last_edited.strftime('%Y')
new_directory = create_directory(downloads_folder, year)
move_file(path, new_directory)
end
end
organize_downloads(downloads_folder, yearly_folders)
So, when the app is started, running the organize_downloads
method, the same old logic used for getting the files, and year modified as explained in part 1.
When it starts to differ is when assigning new_directory
to the value of create_directory
.
1 create_directory
In this method, we give it two attributes: directory
and year
, which is set in organize_downloads
. It then creates a new variable, that eventually just returns a path to the location we want to put the file in.
From there we create a new folder with the new path, UNLESS
the folder already exist.
And finally, we return the final_folder
path.
Now, back to organize_downloads
and what happens in move_file
2 move_file
Here, we give it two attributes: path
, which basically is the pointer to the file itself, and new_directory
which is the return that we got from the create_directory
in step 1.
In here, we again create a final_directory
, but this time to also include subfolders.
This one is pretty easy, it re-uses the create_directory
method again, but to create the subfolder. But instead of having the downloads_folder
and year
, we instead give it the updated directory(directory
) and the return of whatever check_type
does (explained in step 3).
And after getting these values, we run the same FileUtils.mv
to just move it to its new location.
3 check_type
The last piece of the puzzle to explain, and the easiest. A switch condition that checks if the letters/digits after "." at the end of the filename matches a specific set of filetypes set by me.
How I decided to structure mine was:
- Media (images/videos)
- Programs (apps, installers)
- Documents (PDFs, docs)
- Archives (rar-files etc)
- Other (The rest)
I'm sure I've probably missed filetypes etc, but I just wanted to get it to work really.
It then returns a string for whatever match it gets, and then goes on with the logic back in move_file
.
And that's it! Version 2.0 of my Ruby app organizing the downloads folder. Good times.
In the future I would like to look at:
- Add more structure
- Potentially make it even more dynamic and take inputs
- GUI? 👀
Top comments (0)