Search code examples
rubymatrixdirectorycopyidentifier

Ruby Script: Copying files from one folder to multiple others, based on different names


I am very new to programming and coding and have recently started to learn Ruby. My question is this:

I have a bunch of files (around 400) in a folder each with identifiers that group them into 4 separate groups. I want to be able to write a script that will look at this folder, identify the files in the 4 different groups and then copy the files to four separate folders named after the identifier. Is this possible to do?

If this is, would it then be possible to copy files into the different folders based on a matrix of which identifier can overlap in the folder?

For example, lets say each file belonged to four different people: Bob, Harry, Tom, Steve. (These acting as the identifier on the end of the files).

  1. Bob can have files from himself, and Harry but not the other two.
  2. Harry can have files from himself, Bob, Tom, but not Steve.
  3. Tom can have files from himself Harry and Steve, but not Bob.
  4. Steve can have files from himself and Tom but not the other two.

Could I write a script to look at the files and duplicate them to the four different folders, based on the parameters above?

If not in Ruby, is there another programming language that could do this?

Thanks for the help!


Solution

  • Here is an example to get you started. I modified your test files to the form ExampleA_Bob to make it easier to get the identifier.

    To test simply put file_testing.rb and file_owner.rb in a folder and run with ruby file_testing.rb. It will make the test files and also copy them to folders for each person based on whether they are allowed to view them.

    file_testing.rb

    require "fileutils"
    require_relative "file_owner"
    
    # -----------------------------------------------------------------------------
    # ---Helper Functions----------------------------------------------------------
    # -----------------------------------------------------------------------------
    def create_test_files(directory_for_files, file_names)
      FileUtils.mkdir_p(directory_for_files)
      file_names.each{ |file_name|
        out_file = File.new("#{directory_for_files}#{file_name}", "w")
        out_file.puts("Testing #{file_name}")
        out_file.close
      }
    end
    
    def create_file_owners(file_owner_permissions, path_to_files)
      file_owners = []
      file_owner_permissions.each{ |owner_name, owner_permissions|
        file_owners.push(FileOwner.new(owner_name.to_s, owner_permissions, path_to_files))
      }
    
      return file_owners
    end
    
    def parse_file_identifier(file_name)
      split_name = file_name.split("_")
      return split_name[-1]
    end
    
    def sort_files(file_owners, path_to_files)
      Dir.foreach(path_to_files) do |file|
        next if file == "." or file == ".."
        next if File.directory?(path_to_files + file)
    
        file_owners.each{ |owner|
          file_identifier = parse_file_identifier(file)
          owner.copy_file_if_allowed(path_to_files + file, file_identifier)
        }
      end
    end
    
    # -----------------------------------------------------------------------------
    # ---Main----------------------------------------------------------------------
    # -----------------------------------------------------------------------------
    path_to_files = "./test_files/"
    file_names = ["ExampleA_Bob", "ExampleB_Bob", "ExampleC_Bob", "ExampleA_Harry", "ExampleB_Harry", "ExampleC_Harry", "ExampleA_Tom", "ExampleB_Tom", "ExampleC_Tom", "ExampleA_Steve", "ExampleB_Steve", "ExampleC_Steve"]
    create_test_files(path_to_files, file_names)
    
    file_owner_permissions = {
      "Bob": ["Harry"],
      "Harry": ["Bob", "Tom"],
      "Tom": ["Harry", "Steve"],
      "Steve": ["Tom"]
    }
    file_owners = create_file_owners(file_owner_permissions, path_to_files)
    sort_files(file_owners, path_to_files)
    

    file_owner.rb

    require 'fileutils'
    class FileOwner
      attr_accessor :name
      attr_accessor :permissions
    
      def initialize(name, permissions, path_to_files)
        @name = name
        @permissions = permissions.push(name)
        @personal_folder = path_to_files + name
        ensure_personal_folder_exists()
      end
    
      public
      def copy_file_if_allowed(file_path, file_identifier)
        if @permissions.include? file_identifier
          add_file_to_personal_folder(file_path)
        end
      end
    
      private
      def ensure_personal_folder_exists()
        FileUtils.mkdir_p(@personal_folder)
      end
    
      def add_file_to_personal_folder(file_path)
        FileUtils.cp(file_path, @personal_folder)
      end
    end