6

「images」というディレクトリに約100万枚の画像が入っています。うん。

これらすべての画像の名前を次の形式に変更するシェルコマンドを記述したいと思います。

オリジナル: 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*.*またはあなたに合ったもの)

編集:ダンが指摘したように、 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

ただし、ファイルの数を考慮すると、生成する sed および mv プロセスが多数あるため、perl を使用することをお勧めします。

#!/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 スクリプトをお勧めします。ほとんどのシェル ツールは、それだけの量の入力に躊躇します (ただし、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

シェルでワイルドカード構文を使用する提案されたソリューションは、ファイルの数が非常に多いために失敗する可能性があります。現在提案されているソリューションの中で、perlソリューションがおそらく最良です。

ただし、シェルスクリプトメソッドを簡単に適応させて、任意の数のファイルを処理できます。

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

私はまだperlを使用しますが、単純なUNIXツールしか使用できない場合は、上記のシェルソリューションの1つを、私が示したようなループと組み合わせると、そこに到達するはずです。ただし、遅くなります。

于 2009-08-07T03:41:40.013 に答える