Reputation: 199
I have one directory with a number of files and subdirectories. I need to move those files into each subdirectories, depending on their naming. For instance:
Files:
Hello.doc
Hello.txt
Hello.xls
This_is_a_test.doc
This_is_a_test.txt
This_is_a_test.xls
Another_file_to_move.ppt
Another_file_to_move.indd
Subdirectories:
Folder 01 - Hello
Folder 02 - This_is_a_test
Folder 03 - Another_file_to_move
What I need is to move the three files named Hello
into folder Folder 01 - Hello
; the three files called This_is_a_test
into directory Folder 02 - This_is_a_test
and the two files named Another_file_to_move
into directory called Folder 03 - Another_file_to_move
. I have hundreds of files, not just these ones.
As it can be seen, the folder name contain the name of the file at the end, but at the beginning there is a Folder
+ \s
+ a number
+ \s
+ a -
. This is a global pattern.
Any help?
Upvotes: 2
Views: 88
Reputation: 8898
And here is a faster but not cross-platform solution (assuming your working directory is the directory containing the files and subdirectories), and the code is a little bit chaotic:
subdirectories = `ls -d ./*/`.lines.each(&:chomp!)
subdirectories.each do |dir|
basename = dir =~ /\bFolder \d+ - (\w+)\/$/ && $1
next unless basename
`mv ./#{basename}.* #{dir}`
end
Upvotes: 0
Reputation: 8898
Don't rush, try to solve your problem step by step. I would solve your problem in the following steps:
1. Separate files from subdirectories
subdirectories, files = Dir['/path/to/the/directory/*'].partition{|path| File.directory?(path)}
# TODO ...
2. Iterate over the files and retrieve the basename of each file, without extension
subdirectories, files = Dir['/path/to/the/directory/*'].partition{|path| File.directory?(path)}
files.each do |file|
basename = File.basename(file, '.*')
# TODO ...
end
3. Find the subdirectory that the file should go to
subdirectories, files = Dir['/path/to/the/directory/*'].partition{|path| File.directory?(path)}
files.each do |file|
basename = File.basename(file, '.*')
subdirectory = subdirectories.find {|d| File.basename(d) =~ /^Folder \d+ - #{Regexp.escape(basename)}$/}
# TODO ...
end
4. Move the file into that directory
require 'fileutils'
subdirectories, files = Dir['/path/to/the/directory/*'].partition{|path| File.directory?(path)}
files.each do |file|
basename = File.basename(file, '.*')
subdirectory = subdirectories.find {|d| File.basename(d) =~ /^Folder \d+ - #{Regexp.escape(basename)}$/}
FileUtils.mv(file, subdirectory + '/')
end
Done. But finding subdirectories using regexp is expensive and we don't want to do this for each file. Can you optimize it?
HINT 1: Trade memory for time.
HINT 2: Hash.
Upvotes: 3