方法を教えてくださいソートファイルのディレクトリに基づくファイル名?
-
23-08-2019 - |
質問
私は膨大な数のファイルはどれもひどい。
いくつか例を挙げてみましょう。
(4)_mr__mcloughlin____.txt
12__sir_john_farr____.txt
(b)mr__chope____.txt
dame_elaine_kellett-bowman____.txt
dr__blackburn______.txt
これらの名前はずの別の一人様(スピーカーをご利用いただけます。誰か他のIT部門れからのトのXMLファイルをいくつかのスクリプトのネーミングはunfathomably愚かなことがご覧いただけます。
いう文字通り何万人ものこれらのファイルに複数のファイルの文人;それぞれに何かのファイル名の異なる、より頻繁にまたは一部をランダム番号です。れている必要があるソートによるスピーカーです。
このしやすいと思うし、スクリプトのほとんどの作業することが出来ただけで、統合フォルダはどうあるべきか同じ名前などを実行します。
あなたの考えを行っています。
- 構文解析の名称からそれぞれのファイルの並び替えではフォルダ毎に固有の名前を付けます。
- 一覧を取得し、ユニークな名前のファイル名をより簡単にリストのユニークな名前を同様のものと聞かれ、一度決定いたしましたのでここでソートします。
Iプランの利用Perl出すことはできなかったがってみては新しい言語の場合は使い勝手は大きく変わります。なんなのかどうかについては各ファイル名にディレクトリの一つで、文字列の構文解析を実際の名前です。私なんかを解析とregex perlは、それgoogleable.
の選別などは予告なく変更になっ軒のシェルコマンド:
`cp filename.txt /example/destination/filename.txt`
もりであることになるすべてのいのです。
んでもって擬似コードにとっimうかが誰かを知って最良の配列の行動は、すべての耳を信じることにしました。思いがものすごく協力してください、私はプログラムをご提案します。多くの多く、より多くの方に助けることができる。
B.
解決
私はそれが少し曖昧な私見ですが、私はあなたの質問の権利を理解してほしいです。このコードはテストされていないですが、私はあなたがしたいと思う何をすべきます。
use File::Copy;
sub sanatize {
local $_ = shift;
s/\b(?:dame|dr|mr|sir)\b|\d+|\(\w+\)|.txt$//g;
s/[ _]+/ /g;
s/^ | $//g;
return lc $_;
}
sub sort_files_to_dirs {
my @files = @_;
for my $filename (@files) {
my $dirname = sanatize($filename);
mkdir $dirname if not -e $dirname;
copy($filename, "$dirname/$filename");
}
}
他のヒント
同じディレクトリ内のすべての現在のファイルがありますか?その場合は、あなたは、すべてのファイル一つ一つを読みする「opendir関数」と「のreaddir」を使用することができます。あなたはこのような何かを得るように(すべて「_」だけでなく、カッコ内の任意の情報を削除)キーとしてファイル名を使用してハッシュを構築する -
(4)_mr__mcloughlin____.txt -> 'mr mcloughlin'
12__sir_john_farr____.txt -> 'sir john farr'
(b)mr__chope____.txt -> 'mr chope'
dame_elaine_kellett-bowman____.txt -> 'dame elaine kellett-bowman'
dr__blackburn______.txt -> 'dr blackburn'
名前のインスタンスの数は、これまでに発生したことをハッシュの値を設定します。だから、これらのエントリの後に、あなたはこのようになりますハッシュを持っている必要があります -
'mr mcloughlin' => 1
'sir john farr' => 1
'mr chope' => 1
'dame elaine kellett-bowman' => 1
'dr blackburn' => 1
あなたは、ハッシュ内の新しいエントリに遭遇するたびに、単純にキー名を使用して、新しいディレクトリを作成します。今あなたがしなければならないすべては、新しいディレクトリに変更した名前(接尾辞として対応するハッシュ値を使用)を使用してファイルをコピーしています。そうするために例えば、あなたの「ミスターマクローリン」を使用すると、
として、それをコピーすることができて読み込む別のエントリ時につまずくしました./mr mcloughlin/mr mcloughlin_2.txt
い:
の定義とはどの著名:
- は
dr__blackburn
異なるよdr_blackburn
? - は
dr__blackburn
異なるよmr__blackburn
? - 先番号の意味
- ているレンマに意味
- など。
- は
ちのステークホルダーにアルゴリズムに変換するには名前のディレクトリ(レオンは非常に良いスタート)
読み込みの名前で処理することにより、一時
- 混雑して待たされることの組み合わせでopendir、再帰
- 私はコピーして使って処理;再びレオンの後にはあ
このスクリプトが必要となる維持および将来の使用、ゲを試験などを使用 http://search.cpan.org/dist/Test-More/ 各regexpパスただ新しいシワを加え、新たな試験と必ず失敗した場合に、さらに固regex、再テストを実行しくなっ
私はしばらくの間でPerlを使用していませんでした。私はいくつかの擬似コードを確立するためにそれをコメントします。
DESTINATION = '/some/faraway/place/must/exist/and/ideally/be/empty'
# get a list of all .txt files in current directory
Dir["*.txt"].each do |filename|
# strategy:
# - chop off the extension
# - switch to all lowercase
# - get rid of everything but spaces, dashes, letters, underscores
# - then swap any run of spaces, dashes, and underscores for a single space
# - then strip whitespace off front and back
name = File.basename(filename).downcase.
gsub(/[^a-z_\s-]+/, '').gsub(/[_\s-]+/, ' ').strip
target_folder = DESTINATION + '/' + name
# make sure we dont overwrite a file
if File.exists?(target_folder) && !File.directory?(target_folder)
raise "Destination folder is a file"
# if directory doesnt exist then create it
elsif !File.exists?(target_folder)
Dir.mkdir(target_folder)
end
# now copy the file
File.copy(filename, target_folder)
end
これはとにかく、アイデアだ - 私は、すべてのAPI呼び出しが正しいことを確認作りましたが、これは、コードをテストされていません。これはあなたが達成しようとしているもののように見えていますか?このヘルプは、あなたがPerlでコードを書くのでしょうか?
は、
のようなものを使用してファイル名を分割することができます@tokens = split /_+/, $filename
@tokens
の最後のエントリは、これらのファイル名のすべてについて".txt"
する必要がありますが、最後から2番目のは、その名の場所にスペルミス(または「ジョーンズ博士は」ブライアン・ジョーンズ」に変更された同じ人のために類似していなければなりません" 例えば)。あなたは、さまざまなファイル名の@tokens[-2]
を比較するメトリック類似度として編集距離でのいくつかの並べ替えを使用することもできます; 2つのエントリが最後十分似た名前を持つとき、彼らはマージの候補としてプロンプトを表示する必要があります。
、任意の言語がある限り、我々はルールのより良い成文化を持っているとして、これを行うことができます。私たちも、の詳細の、唯一の「サンプル」を持っていません。
人間の監視が必要になりますようにだから、ブラインド作業、それが見えます。だから、アイデアは、のふるいのです。あなたが繰り返し実行して確認して再実行し、いくつかの小さな手動タスクにソートされたすべてのものを持ってまで、何度も何度も確認することができるもの。
あなたはかなりそれを処理するために私たちにそれを残しているため、以下のコードは、の仮定の多くの になります。一つは、サンプルは、すべての可能な最後の名前のリストであるということです。他の姓がある場合は、「日を追加して、再度実行します。
use strict;
use warnings;
use File::Copy;
use File::Find::Rule;
use File::Spec;
use Readonly;
Readonly my $SOURCE_ROOT => '/mess/they/left';
Readonly my $DEST_DIRECTORY => '/where/i/want/all/this';
my @lname_list = qw<mcloughlin farr chope kelette-bowman blackburn>;
my $lname_regex
= join( '|'
, sort { ( $b =~ /\P{Alpha}/ ) <=> ( $a =~ /\P{Alpha}/ )
|| ( length $b ) <=> ( length $a )
|| $a cmp $b
} @lname_list
)
;
my %dest_dir_for;
sub get_dest_directory {
my $case = shift;
my $dest_dir = $dest_dir_for{$case};
return $dest_dir if $dest_dir;
$dest_dir = $dest_dir_for{$case}
= File::Spec->catfile( $DEST_DIRECTORY, $case )
;
unless ( -e $dest_dir ) {
mkdir $dest_dir;
}
return $dest_dir;
}
foreach my $file_path (
File::Find::Rule->file
->name( '*.txt' )->in( $SOURCE_ROOT )
) {
my $file_name = [ File::Spec->splitpath( $file_path ) ]->[2];
$file_name =~ s/[^\p{Alpha}.-]+/_/g;
$file_name =~ s/^_//;
$file_name =~ s/_[.]/./;
my ( $case ) = $file_name =~ m/(^|_)($lname_regex)[._]/i;
next unless $case;
# as we next-ed, we're dealing with only the cases we want here.
move( $file_path
, File::Spec->catfile( get_dest_directory( lc $case )
, $file_name
)
);
}