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个文件夹中(不用按顺序)。
1.png
(25.66 KB, 下载次数: 112)
下载附件
A1-5
2014-09-22 08:17 上传
如何实现,怎样才能保证高效?
作者:
bulletmarquis
时间:
2014-09-22 09:02
本帖最后由 bulletmarquis 于 2014-09-22 09:31 编辑
我的习惯
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个文件做测试,先创建文件和目录
touch {a..z}{1..5}
mkdir 1 2 3 4 5
复制代码
下面处理时,每20个文件操作一次,测试效果(当然LZ文件很多,20个太小了,可以将NR%20==0改成合适的值)
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 ""}'
cp -f a3 b3 c3 d3 4/
cp -f a4 b4 c4 d4 5/
cp -f a5 b5 c5 d5 1/
cp -f a1 b1 c1 d1 2/
cp -f a2 b2 c2 d2 3/
cp -f e3 f3 g3 h3 4/
cp -f e4 f4 g4 h4 5/
cp -f e5 f5 g5 h5 1/
cp -f e1 f1 g1 h1 2/
cp -f e2 f2 g2 h2 3/
cp -f i3 j3 k3 l3 4/
cp -f i4 j4 k4 l4 5/
cp -f i5 j5 k5 l5 1/
cp -f i1 j1 k1 l1 2/
cp -f i2 j2 k2 l2 3/
cp -f m3 n3 o3 p3 4/
cp -f m4 n4 o4 p4 5/
cp -f m5 n5 o5 p5 1/
cp -f m1 n1 o1 p1 2/
cp -f m2 n2 o2 p2 3/
cp -f q3 r3 s3 t3 4/
cp -f q4 r4 s4 t4 5/
cp -f q5 r5 s5 t5 1/
cp -f q1 r1 s1 t1 2/
cp -f q2 r2 s2 t2 3/
cp -f u3 v3 w3 x3 4/
cp -f u4 v4 w4 x4 5/
cp -f u5 v5 w5 x5 1/
cp -f u1 v1 w1 x1 2/
cp -f u2 v2 w2 x2 3/
复制代码
实际执行
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
感觉可以这样,无法测试,请谨慎使用.
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
确实考虑不周,修改了一下
构造数据
echo {a..z}{1..5}|awk -vRS=" " '{print "" > $0" "$0}'
mkdir 1 2 3 4 5
复制代码
测试效果
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 ""}'
复制代码
实际执行
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
大概是这样:
ls | split -l 200000
mkdir {0..4}
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
mkdir {1..5}
prefix=prefix$$
find -maxdepth 1 -type f -name '*.txt' | split -l 200000 -d -a1 - $prefix
for i in {1..5};do xargs -a $prefix$i -d '\n' mv -i -t $i;done
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个$的实际效果:
$
#2个$的实际效果:
$
#3个$的实际效果:
$$
#4个$的实际效果:
$$
复制代码
作者:
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