6

我有一个名为“images”的目录,里面有大约一百万张图片。是的。

我想编写一个 shell 命令将所有这些图像重命名为以下格式:

原: filename.jpg
新: /f/i/l/filename.jpg

有什么建议么?

谢谢,

4

5 回答 5

7
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*.*适合您的选项)

编辑:如 Dan 所述,在for$之前添加了一个imv

于 2009-08-07T03:22:04.607 回答
2

您可以使用例如 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它来解决这个问题。

于 2009-08-07T03:12:20.377 回答
2

您可以将其作为 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

不用说,您可能需要担心空格和短名称的文件。

于 2009-08-07T03:30:17.913 回答
1

我建议一个简短的 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)
于 2009-08-07T03:12:36.977 回答
0

由于您拥有的文件数量庞大,任何在 shell 中使用通配符语法的建议解决方案都可能会失败。在当前提出的解决方案中,perl 可能是最好的。

但是,您可以轻松地调整任何 shell 脚本方法来处理任意数量的文件,因此:

ls -1 | \
while read filename
do
  # insert the loop body of your preference here, operating on "filename"
done

我仍然会使用 perl,但如果您仅限于使用简单的 unix 工具,那么将上述 shell 解决方案之一与我展示的循环结合起来应该可以帮助您。不过会很慢。

于 2009-08-07T03:41:40.013 回答