Chinaunix

标题: 如何高效地将大量小文件平均分到各个文件夹中? [打印本页]

作者: iocg    时间: 2014-09-22 08:17
标题: 如何高效地将大量小文件平均分到各个文件夹中?
本帖最后由 iocg 于 2014-09-22 09:01 编辑

现某文件夹A下有100w个小文件(.txt),大小10K左右。

假设文件数量的阈值设为20W。
将在A文件夹自动生成5个文件夹(命名:1~5),将100W个文件每20W个移动至5个文件夹中(不用按顺序)。

如何实现,怎样才能保证高效?


作者: bulletmarquis    时间: 2014-09-22 09:02
本帖最后由 bulletmarquis 于 2014-09-22 09:31 编辑

我的习惯
  1. ll|grep ^-|awk '{_cmd_="cp -f "$NF" "NR%5+1"/";_cmd_|getline;close(_cmd_)}'
复制代码
不过文件多的话,逐个cp或者mv效率不高,可以改成先把文件名写到数组里,等攒到一定数量,再拼装cp语句
作者: iocg    时间: 2014-09-22 09:22
回复 2# bulletmarquis


    拼装cp语句?求大神解释。。
作者: bulletmarquis    时间: 2014-09-22 09:35
本帖最后由 bulletmarquis 于 2014-09-22 10:02 编辑

回复 3# iocg


    拿26*5个文件做测试,先创建文件和目录
  1. touch {a..z}{1..5}
  2. mkdir 1 2 3 4 5
复制代码
下面处理时,每20个文件操作一次,测试效果(当然LZ文件很多,20个太小了,可以将NR%20==0改成合适的值)
  1. ll|grep ^-|awk '{a[NR%5+1]=a[NR%5+1]" "$NF}NR%20==0{for (i in a){_cmd_="cp -f "a[i]" "i"/";print _cmd_}delete a;print ""}'
  2. cp -f  a3 b3 c3 d3 4/
  3. cp -f  a4 b4 c4 d4 5/
  4. cp -f  a5 b5 c5 d5 1/
  5. cp -f  a1 b1 c1 d1 2/
  6. cp -f  a2 b2 c2 d2 3/

  7. cp -f  e3 f3 g3 h3 4/
  8. cp -f  e4 f4 g4 h4 5/
  9. cp -f  e5 f5 g5 h5 1/
  10. cp -f  e1 f1 g1 h1 2/
  11. cp -f  e2 f2 g2 h2 3/

  12. cp -f  i3 j3 k3 l3 4/
  13. cp -f  i4 j4 k4 l4 5/
  14. cp -f  i5 j5 k5 l5 1/
  15. cp -f  i1 j1 k1 l1 2/
  16. cp -f  i2 j2 k2 l2 3/

  17. cp -f  m3 n3 o3 p3 4/
  18. cp -f  m4 n4 o4 p4 5/
  19. cp -f  m5 n5 o5 p5 1/
  20. cp -f  m1 n1 o1 p1 2/
  21. cp -f  m2 n2 o2 p2 3/

  22. cp -f  q3 r3 s3 t3 4/
  23. cp -f  q4 r4 s4 t4 5/
  24. cp -f  q5 r5 s5 t5 1/
  25. cp -f  q1 r1 s1 t1 2/
  26. cp -f  q2 r2 s2 t2 3/

  27. cp -f  u3 v3 w3 x3 4/
  28. cp -f  u4 v4 w4 x4 5/
  29. cp -f  u5 v5 w5 x5 1/
  30. cp -f  u1 v1 w1 x1 2/
  31. cp -f  u2 v2 w2 x2 3/
复制代码
实际执行
  1. ll|grep ^-|awk '{a[NR%5+1]=a[NR%5+1]" "$NF}NR%20==0{for (i in a){_cmd_="cp -f "a[i]" "i"/";_cmd_|getline;close(_cmd_)}delete a}'
复制代码

作者: Herowinter    时间: 2014-09-22 10:07
本帖最后由 Herowinter 于 2014-09-22 11:05 编辑

回复 1# iocg

感觉可以这样,无法测试,请谨慎使用.
  1. for((i=1;i<=5;i++));do for((j=1;j<=1000;j++))do ls *.txt|head -200|xargs -i mv "{}" $i;done done
复制代码

作者: Shell_HAT    时间: 2014-09-22 10:48
回复 2# bulletmarquis


    无法处理文件名包含空格的情况吧
作者: bulletmarquis    时间: 2014-09-22 11:03
本帖最后由 bulletmarquis 于 2014-09-22 11:04 编辑

回复 6# Shell_HAT


    确实考虑不周,修改了一下

构造数据
  1. echo {a..z}{1..5}|awk -vRS=" " '{print "" > $0" "$0}'
  2. mkdir 1 2 3 4 5
复制代码
测试效果
  1. ls -F1|grep -v /$|awk '{a[NR%5+1]=a[NR%5+1]" \""$0"\""}NR%20==0{for (i in a){_cmd_="cp -f "a[i]" "i"/";print _cmd_}delete a;print ""}'
复制代码
实际执行
  1. ls -F1|grep -v /$|awk '{a[NR%5+1]=a[NR%5+1]" \""$0"\""}NR%20==0{for (i in a){_cmd_="cp -f "a[i]" "i"/";_cmd_|getline;close(_cmd_)}delete a;print ""}'
复制代码

作者: bulletmarquis    时间: 2014-09-22 11:08
回复 6# Shell_HAT


    搭车请教一下,如果文件名中会有空格的话,有没有好办法只取出文件名来且逐行展示文件名?

   看了半天ls --help,只有
ls -F1|grep -v /$
能行,但是如果目录下还有链接啥的,就很麻烦

   有没有其他好办法?
作者: blackold    时间: 2014-09-22 11:49
回复 1# iocg


    先把文件列表分割到5份(split),即5个文件, 再用这5个文件为输入,xargs mv 文件到相应的文件夹。
作者: yestreenstars    时间: 2014-09-22 11:55
回复 9# blackold

这样效率应该比用for循环高
   
作者: Herowinter    时间: 2014-09-22 12:06
回复 9# blackold

黑哥的算法学得真好,分治法分分钟搞定,不得不服.
   
作者: reyleon    时间: 2014-09-22 13:35
来个伪多进程并发 mv
作者: iocg    时间: 2014-09-22 14:03
回复 9# blackold


    能不能给个代码参考下呢?
作者: yestreenstars    时间: 2014-09-22 14:24
回复 13# iocg

大概是这样:
  1. ls | split -l 200000
  2. mkdir {0..4}
  3. awk '{cmd="mv "$0" "int(NR/200000);system(cmd);close(cmd)}' x*
复制代码

作者: blackold    时间: 2014-09-22 17:43
本帖最后由 blackold 于 2014-09-23 13:29 编辑

回复 13# iocg
  1. mkdir {1..5}

  2. prefix=prefix$$

  3. find -maxdepth 1 -type f -name '*.txt' | split -l 200000 -d -a1 - $prefix

  4. for i in {1..5};do xargs -a $prefix$i -d '\n' mv -i -t $i;done

  5. rm $prefix[0-9]
复制代码
原来不是我的错, 是论坛的错。

@Shell_HAT
作者: bulletmarquis    时间: 2014-09-22 18:42
回复 15# blackold


    黑哥这句 prefix=prefix$ 是啥意思啊?


作者: blackold    时间: 2014-09-22 18:47
回复 16# bulletmarquis


    漏了,是$$
作者: Shell_HAT    时间: 2014-09-23 12:56
回复 17# blackold
  1. #1个$的实际效果:
  2. $
  3. #2个$的实际效果:
  4. $
  5. #3个$的实际效果:
  6. $$
  7. #4个$的实际效果:
  8. $$
复制代码

作者: blackold    时间: 2014-09-23 13:21
本帖最后由 blackold 于 2014-09-23 13:21 编辑

回复 18# Shell_HAT


    Shell_HAT 什么意思? 看不懂。
作者: Shell_HAT    时间: 2014-09-23 13:24
回复 19# blackold


    Discuz论坛的两个JS脚本有bug,两个$符号放在code标签里面会丢掉一个。
作者: blackold    时间: 2014-09-23 13:26
回复 20# Shell_HAT


    是这样啊,以前真没注意。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2