Simple Downloads Folder Organiser Written In Ruby
Tags: ruby, beginners, tutorial
Published: 2020-06-05 18:53:37

This was originally published on [ProjectLode.com](https://projectlode.com/projects/simple-download-folder-organiser/guides/simple-downloads-folder-organiser-written-in-ruby)

We will create a simple script that organises the files in our Downloads (or any folder) into various subfolders (ie Audio, Documents, Video, and Images). This approach is fairly straight forward and can easily be extended to add more extensive features. 
Our script would carry out the following functions:
1. Checks the current folder to see if our desired subfolders are created. If they are not available, they are then created.
2. Move different files to different folders based on the files extensions.
3. Before a file is moved to a subfolder, it checks to see if there is a file with a similar name in the subfolder.
4. Renames the file that is about to be moved to a subfolder if there already is a file with the same name.
We begin by creating a class name called Arranger and requiring the FileUtils module. The FileUtils module would be used to move files around.
```ruby
class Arranger
  require "fileutils"
end
```
We then create a constant Array of the subfolders we want to create.
```ruby
class Arranger
  require 'fileutils'
  FOLDERS = %w[Video Audio Document Images].freeze
end
```
Our first method would check if the subfolders exist in the directory. If they do not exist, we would create them. We go over each element in the FOLDERS array and user "Dir.exist?" to check the subfolders already exist or not. "Dir.mkdir" is then used to create the folders that do not exist.
```ruby
class Arranger
  require 'fileutils'
  FOLDERS = %w[Video Audio Document Images].freeze
  def create_folders_not_existing
    FOLDERS.each do |folder|
      if Dir.exist?(folder)
        puts "#{folder} already exists"
      else
        Dir.mkdir(folder)
      end
    end
  end
end
```
Our next step would be to check if the file we want to move already exists in the subdirectory. Our method would take two parameters; file (ie the file we are moving) and path (the subdirectory's path) It returns true if the file exists and false if it does not exist.
```ruby
class Arranger
  require 'fileutils'
  FOLDERS = %w[Video Audio Document Images].freeze
  def create_folders_not_existing
    FOLDERS.each do |folder|
      if Dir.exist?(folder)
        puts "#{folder} already exists"
      else
        Dir.mkdir(folder)
      end
    end
  end

  def check_if_file_exist_in_path?(file, path)
    FileUtils.cd(path)
    if File.exist?(file)
      FileUtils.cd('../')
      true
    else
      FileUtils.cd('../')
      false
    end
  end
end
```
If a file already exists in the subdirectory, we must rename the file that we want to move. We define a method that does this for us. This method takes a file and assigns its extension to "file_extension". It then takes the file name without the extension and assigns it to "file_name". Finally, we rename this file by splicing the file name with the current time.
```ruby 
class Arranger
  require 'fileutils'
  FOLDERS = %w[Video Audio Document Images].freeze
  def create_folders_not_existing
    FOLDERS.each do |folder|
      if Dir.exist?(folder)
        puts "#{folder} already exists"
      else
        Dir.mkdir(folder)
      end
    end
  end

  def check_if_file_exist_in_path?(file, path)
    FileUtils.cd(path)
    if File.exist?(file)
      FileUtils.cd('../')
      true
    else
      FileUtils.cd('../')
      false
    end
  end


  def rename_file(file)
    puts file_extension = File.extname(file)
    puts file_name = File.basename(file, file_extension)
    File.rename(file, file_name + Time.now.to_s + file_extension)
  end
end
```
We now define methods that would move our desired files into their respective subdirectories. This is first done by looking at each files extension and determining where it should go. We can assume that files ending with "docx", "csv" or "pdf| should go to the Documents folder. Likewise, we would carry out similar procedures for images, audio and videos. We then check if the file already exists in the subdirectory. If it does not exist, we move the file using "FileUtils.mv". If it does exist, we rename the file and then move it. I defined a method to do this for each folder, but this could be written in one simple method as there is a lot of repetition going on.
```ruby 
# frozen_string_literal: true

# class Arranger
class Arranger
  require 'fileutils'
  FOLDERS = %w[Video Audio Document Images].freeze
  def create_folders_not_existing
    FOLDERS.each do |folder|
      if Dir.exist?(folder)
        puts "#{folder} already exists"
      else
        Dir.mkdir(folder)
      end
    end
  end

  def move_images
    images = Dir.glob('*.{jpg,jpeg,png}')
    images.each do |image|
      if check_if_file_exist_in_path?(image, './Images')
        rename_file(image)
        move_images
        break
      else
        FileUtils.mv(image, './Images')
      end
      puts "Moved #{image} to Images"
    end
  end

  def move_video
    videos = Dir.glob('*.{mp4,avi,mkv}')
    videos.each do |video|
      if check_if_file_exist_in_path?(video, './Video')
        rename_file(video)
        move_video
        break
      else
        FileUtils.mv(video, './Video')
      end
      puts "Moved #{video} to Video"
    end
  end

  def move_document
    documents = Dir.glob('*.{docx,csv,pdf,PDF,epub,gif,pptx,xlsx}')
    documents.each do |document|
      if check_if_file_exist_in_path?(document, './Document')
        rename_file(document)
        move_document
        break
      else
        FileUtils.mv(document, './Document')
      end
      puts "Moved #{document} to Document"
    end
  end

  def move_audio
    audios = Dir.glob('*.{mp3}')
    audios.each do |audio|
      if check_if_file_exist_in_path?(audio, './Audio')
        rename_file(audio)
        move_audio
        break
      else
        FileUtils.mv(audio, './Audio')
      end
      puts "Moved #{audio} to Audio"
    end
  end

  def check_if_file_exist_in_path?(file, path)
    FileUtils.cd(path)
    if File.exist?(file)
      FileUtils.cd('../')
      true
    else
      FileUtils.cd('../')
      false
    end
  end

  def rename_file(file)
    puts file_extension = File.extname(file)
    puts file_name = File.basename(file, file_extension)
    File.rename(file, file_name + Time.now.to_s + file_extension)
  end
end
```
Finally, we define a method that calls all the move functions. The final source code for the script is presented below. 
```ruby
# frozen_string_literal: true

# class Arranger
class Arranger
  require 'fileutils'
  FOLDERS = %w[Video Audio Document Images].freeze
  def create_folders_not_existing
    FOLDERS.each do |folder|
      if Dir.exist?(folder)
        puts "#{folder} already exists"
      else
        Dir.mkdir(folder)
      end
    end
  end

  def move_images
    images = Dir.glob('*.{jpg,jpeg,png}')
    images.each do |image|
      if check_if_file_exist_in_path?(image, './Images')
        rename_file(image)
        move_images
        break
      else
        FileUtils.mv(image, './Images')
      end
      puts "Moved #{image} to Images"
    end
  end

  def move_video
    videos = Dir.glob('*.{mp4,avi,mkv}')
    videos.each do |video|
      if check_if_file_exist_in_path?(video, './Video')
        rename_file(video)
        move_video
        break
      else
        FileUtils.mv(video, './Video')
      end
      puts "Moved #{video} to Video"
    end
  end

  def move_document
    documents = Dir.glob('*.{docx,csv,pdf,PDF,epub,gif,pptx,xlsx}')
    documents.each do |document|
      if check_if_file_exist_in_path?(document, './Document')
        rename_file(document)
        move_document
        break
      else
        FileUtils.mv(document, './Document')
      end
      puts "Moved #{document} to Document"
    end
  end

  def move_audio
    audios = Dir.glob('*.{mp3}')
    audios.each do |audio|
      if check_if_file_exist_in_path?(audio, './Audio')
        rename_file(audio)
        move_audio
        break
      else
        FileUtils.mv(audio, './Audio')
      end
      puts "Moved #{audio} to Audio"
    end
  end

  def check_if_file_exist_in_path?(file, path)
    FileUtils.cd(path)
    if File.exist?(file)
      FileUtils.cd('../')
      true
    else
      FileUtils.cd('../')
      false
    end
  end

  def rename_file(file)
    puts file_extension = File.extname(file)
    puts file_name = File.basename(file, file_extension)
    File.rename(file, file_name + Time.now.to_s + file_extension)
  end

  def call_all_move_methods
    move_audio
    move_document
    move_images
    move_video
  end
end

arranger = Arranger.new
arranger.create_folders_not_existing
loop do
  arranger.call_all_move_methods
end

```
The source code for this is available at https://github.com/timnans/arranger