有8000个文件在一个文件夹src里面,要分别复制到另外8个文件夹下的文件夹里面,用ruby如何实现

有8000个文件在一个文件夹src里面,要分别复制到另外8个文件夹下的文件夹里面,用ruby如何实现呢?

例如8个目标文件夹名分别为(1000,2000,3000,4000,5000,6000,7000,8000)
在目标文件夹1000里面新建文件夹1里面存放第一个文件,新建文件夹2里面存放第二个文件,一直到新建文件夹1000里面存放第1000个文件,
在目标文件夹2000里面新建文件夹1001存放第1001个文件,新建文件夹1002存放第1002个文件,一直到新建文件夹2000存放第2000个文件
在目标文件夹3000里面新建文件夹2001存放第2001个文件,新建文件夹2002存放第2002个文件,一直到新建文件夹3000存放第3000个文件
在目标文件夹4000里面新建文件夹3001存放第3001个文件,新建文件夹3002存放第3002个文件,一直到新建文件夹4000存放第4000个文件
在目标文件夹5000里面新建文件夹4001存放第4001个文件,新建文件夹4002存放第4002个文件,一直到新建文件夹5000存放第5000个文件
在目标文件夹6000里面新建文件夹5001存放第5001个文件,新建文件夹5002存放第5002个文件,一直到新建文件夹6000存放第6000个文件
以此类推,直至源文件夹里面文件都存放完毕

[quote="liyu212"] 1. require 'ftools'


  1. # assume all paths in destdirs are valid directories
  2. def copy_all(srcdir, destdirs)
  3. Dir.entries(srcdir)[2..-1].each_with_index do |fname, idx|
  4. Dir.mkdir(dir = File.join(destdirs[idx / 1000], (idx + 1).to_s))
  5. File.copy File.join(srcdir, fname), File.join(dir, fname)
  6. end
  7. end

    1. # change the paths here, or take them
    2. # from command line arguments (ARGV)
    3. srcdir = './src'
    4. destdirs = (1..8).map {|i| "./dest/#{i}000"}

    5. # copy the files
    6. copy_all srcdir, destdirs

destdirs[idx / 1000],这个代码有什么作用呢?

还有,如果我提前不知道srcdir文件夹中的文件个数,该怎么完善这个程序呢?[/quote]
首先destdirs是我给copy_all设的一个参数,它期待接受的是含有所有可用的输出目录路径的一个数组。
为了保持代码的灵活性,我没有把1000..8000那8个目录的路径直接写在copy_all里,而是在调用copy_all时从外部传入那些路径名。传进去的数组内容是这样组装出来的:
[code="ruby"]destdirs = (1..8).map {|i| "./dest/#{i}000"}
#=> ["./dest/1000", "./dest/2000", "./dest/3000", "./dest/4000", "./dest/5000", "./dest/6000", "./dest/7000", "./dest/8000"][/code]
也就是说,传进去的数组的第一个元素(下标为0那个)就是"./dest/1000"。
而遍历srcdir文件夹里的内容时,Dir.entries返回的是包括"."和".."在内的所有文件和子文件夹。忽略掉"."和".."后,调用each_with_index,在block里的idx就可以获得文件的序号(从0开始)。那么头1000个文件的序号就是0到999。这些数字除以1000都等于0,正好从destdirs数组里就找到对应的下标的那个路径,也就是你问的destdirs[idx / 1000]。

这段代码我因为懒所以少做了些检查,本来最好是检查一下fname对应的是不是文件,类似:
[code="ruby"]fpath = File.join(srcdir, fname)
File.file? fpath[/code]
另外,反正用到了ftools,新建目录的时候可能用File.mkpath会好一点(上面的代码里用的是Dir.mkdir)。
然后如果你要在copy_all里直接生成那些目标目录(1000...8000那些),那可以像这样:
[code="ruby"]require 'ftools'

参数:

srcdir : 要拷贝的文件所在的文件夹

destdir : 要拷贝的文件的目标文件夹

file_per_dir : 目标目录里每个文件夹要放多少个文件

def copy_all(srcdir, destdir, file_per_dir)

# 得到srcdir目录下的所有文件,不包括子文件夹及子文件夹里的文件
# 下面几行都可以写在一行上,这里只是为了看起来方便所以换行了
entries = Dir.entries(srcdir).
map {|f| File.join srcdir, f }.
select {|f| File.file? f }

# 得到文件夹的数目
len = entries.length
dir_count = len / file_per_dir +
((len % file_per_dir == 0) ? 0 : 1)
# 得到分组的目标文件夹
destdirs = (1..dir_count).
map {|i| File.join destdir, (i * file_per_dir).to_s }
# 创建这些目标文件夹
destdirs.each {|d| File.mkpath d }

# 拷贝文件……
entries.each_with_index do |fpath, idx|
dir = File.join destdirs[idx / file_per_dir], (idx + 1).to_s
File.mkpath dir
File.copy fpath, File.join(dir, File.basename(fpath))
end
end

类似这样来调用

copy_all './src', './dest', 10[/code]
反正根据你自己的需要来改吧~

require 'fileutils'
用 FileUtils.mkdir
和 FileUtils.cp
写两个循环即可

加上选项:noop可以看结果而不执行实际操作

类似这样么……
[code="ruby"]require 'ftools'

assume all paths in destdirs are valid directories

def copy_all(srcdir, destdirs)
Dir.entries(srcdir)[2..-1].each_with_index do |fname, idx|
Dir.mkdir(dir = File.join(destdirs[idx / 1000], (idx + 1).to_s))
File.copy File.join(srcdir, fname), File.join(dir, fname)
end
end

change the paths here, or take them

from command line arguments (ARGV)

srcdir = './src'
destdirs = (1..8).map {|i| "./dest/#{i}000"}

copy the files

copy_all srcdir, destdirs[/code]