我有一个名为“images”的目录,里面充满了约100万张图像。是的。Linux:将100万个文件移动到基于前缀的已创建文件夹中
我想写一个shell命令将所有这些图像的重命名为以下格式:
原:filename.jpg
新:/f/i/l/filename.jpg
有什么建议?
感谢,
丹
我有一个名为“images”的目录,里面充满了约100万张图像。是的。Linux:将100万个文件移动到基于前缀的已创建文件夹中
我想写一个shell命令将所有这些图像的重命名为以下格式:
原:filename.jpg
新:/f/i/l/filename.jpg
有什么建议?
感谢,
丹
for i in *.*; do mkdir -p ${i:0:1}/${i:1:1}/${i:2:1}/; mv $i ${i:0:1}/${i:1:1}/${i:2:1}/; done;
的${i:0:1}/${i:1:1}/${i:2:1}
部分可能会是一个变量,或短或不同,但上面的命令能够完成任务。您可能会遇到性能问题,但如果你真的想使用它,缩小*.*
较少的选项(a*.*
,b*.*
或什么适合你)
编辑:i
前添加一个$
为mv
,由丹
可以使用,例如,sed中生成新的文件名:
$ echo "test.jpg" | sed -e 's/^\(\(.\)\(.\)\(.\).*\)$/\2\/\3\/\4\/\1/'
t/e/s/test.jpg
所以,你可以做这样的事情(假设所有的目录,已经创建) :
for f in *; do
mv -i "$f" "$(echo "$f" | sed -e 's/^\(\(.\)\(.\)\(.\).*\)$/\2\/\3\/\4\/\1/')"
done
,或者,如果你不能使用bash的$(
语法:
for f in *; do
mv -i "$f" "`echo "$f" | sed -e 's/^\(\(.\)\(.\)\(.\).*\)$/\2\/\3\/\4\/\1/'`"
done
然而,考虑到文件的数量,你可能只是想用perl因为这是很多SED和MV的过程中产卵:
#!/usr/bin/perl -w
use strict;
# warning: untested
opendir DIR, "." or die "opendir: $!";
my @files = readdir(DIR); # can't change dir while reading: read in advance
closedir DIR;
foreach my $f (@files) {
(my $new_name = $f) =~ s!^((.)(.)(.).*)$!$2/$3/$4/$1/;
-e $new_name and die "$new_name already exists";
rename($f, $new_name);
}
是Perl是肯定仅限于同一文件系统只,尽管你可以使用File::Copy::move
来解决这个问题。
我建议一个简短的python脚本。大多数shell工具都会忽略这么多的输入(尽管xargs可能会做到这一点)。将在一秒内以示例进行更新。
#!/usr/bin/python
import os, shutil
src_dir = '/src/dir'
dest_dir = '/dest/dir'
for fn in os.listdir(src_dir):
os.makedirs(dest_dir+'/'+fn[0]+'/'+fn[1]+'/'+fn[2]+'/')
shutil.copyfile(src_dir+'/'+fn, dest_dir+'/'+fn[0]+'/'+fn[1]+'/'+fn[2]+'/'+fn)
感谢,看起来像一个美妙的解决方案。我需要等待文件传输到我的新服务器才可以试用(ETA 50小时大声笑) – Dan 2009-08-07 06:38:19
你可以做到这一点作为一个bash脚本:
#!/bin/bash
base=base
mkdir -p $base/shorts
for n in *
do
if [ ${#n} -lt 3 ]
then
mv $n $base/shorts
else
dir=$base/${n:0:1}/${n:1:1}/${n:2:1}
mkdir -p $dir
mv $n $dir
fi
done
不用说,你可能需要担心的空间和一个带有短名的文件。
非常好的解决方案,谢谢 – Dan 2009-08-07 06:41:45
任何在shell中使用通配符语法的建议解决方案都可能因为您拥有的文件数量太多而失败。在目前提出的解决方案中,perl可能是最好的解决方案。
但是,您可以轻松地适应任何的shell脚本的方法来处理任意数量的文件这样的:
ls -1 | \
while read filename
do
# insert the loop body of your preference here, operating on "filename"
done
我仍然会用perl,但如果你只限于有简单的Unix工具然后将上面的一个shell解决方案与我之前展示的一个循环结合起来,就可以让你在那里。不过,它会很慢。
100万图片eh?这是很多色情片! – 2009-08-11 21:25:18