「images」というディレクトリに約100万枚の画像が入っています。うん。
これらすべての画像の名前を次の形式に変更するシェルコマンドを記述したいと思います。
オリジナル: 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*.*
またはあなたに合ったもの)
編集:ダンが指摘したように、 forの$
前に追加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
ただし、ファイルの数を考慮すると、生成する 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
回避するために使用できます.
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
言うまでもなく、スペースや短い名前のファイルについて心配する必要があるかもしれません。
短い 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)
シェルでワイルドカード構文を使用する提案されたソリューションは、ファイルの数が非常に多いために失敗する可能性があります。現在提案されているソリューションの中で、perlソリューションがおそらく最良です。
ただし、シェルスクリプトメソッドを簡単に適応させて、任意の数のファイルを処理できます。
ls -1 | \
while read filename
do
# insert the loop body of your preference here, operating on "filename"
done
私はまだperlを使用しますが、単純なUNIXツールしか使用できない場合は、上記のシェルソリューションの1つを、私が示したようなループと組み合わせると、そこに到達するはずです。ただし、遅くなります。