문제

나는 끔찍한 컨벤션에서 이름을 모두 정렬 할 수있는 수많은 파일이 있습니다.
여기 몇 가지 예가 있어요.

(4) _mr__mcloughlin ____. txt
12__SIR_JOHN_FARR ____. TXT
(b) mr__chope ____. txt
dame_elaine_kellett-bowman ____. txt
dr__blackburn ______. txt

이 이름은 각각 다른 사람 (스피커)이어야합니다. 다른 IT 부서의 누군가가 일부 스크립트를 사용하여 수많은 XML 파일에서이를 제작했지만 이름을 알 수 있듯이 이름 지정은 어리석은 일입니다.

문자 그대로 수만 개의 파일을 각 사람마다 여러 개의 텍스트 파일로 정렬해야합니다. 파일 이름을 다르게 만드는 바보 같은 무언가를 가진 각각은 더 밑줄이 있거나 임의의 숫자가 있습니다. 스피커로 정렬해야합니다.

대부분의 작업을 수행하는 스크립트를 사용하면 더 쉬울 것입니다. 그러면 다시 돌아가서 동일한 이름이나 그 밖의 폴더를 병합 할 수 있습니다.

내가 이것을하는 것에 대해 생각했던 방법에는 여러 가지가 있습니다.

  • 각 파일의 이름을 구문 분석하고 각 고유 이름의 폴더로 정렬하십시오.
  • 파일 이름에서 모든 고유 한 이름의 목록을 얻은 다음 비슷한 이름에 대한이 단순화 된 고유 이름 목록을 살펴보고 동일인지 물어 보면이를 결정하면 그에 따라 정렬 할 것입니다.

나는 Perl을 사용할 계획이지만 그만한 가치가 있다면 새로운 언어를 시도 할 수 있습니다. 각 파일 이름에서 디렉토리의 각 파일 이름에서 한 번에 하나씩 실제 이름으로 구문 분석하기위한 문자열로 읽는 방법을 잘 모르겠습니다. Perl에서 Regex와 구문 분석하는 방법을 완전히 잘 모르겠지만 Googlable 일 수 있습니다.

정렬을 위해, 나는 단지 shell 명령을 사용했습니다.

`cp filename.txt /example/destination/filename.txt`

그러나 그게 내가 아는 전부이기 때문에 가장 쉬운 일입니다.

나는 내가 무엇을 할 것인지에 대한 의사 코드 아이디어조차 없기 때문에 누군가가 최고의 행동 순서를 알고 있다면 모든 귀가 있습니다. 나는 많은 도움을 찾고 있다고 생각합니다. 어떤 제안에도 열려 있습니다. 도움을 줄 수있는 사람에게 감사드립니다.

비.

도움이 되었습니까?

해결책

나는 당신의 질문을 올바르게 이해하기를 바랍니다. 그것은 약간 모호한 IMHO입니다. 이 코드는 테스트되지 않았지만 내가 원하는 것을해야합니다.

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/mr mcloughlin_2.txt

나는 :

  1. 이름에서 중요한 것을 정의하십시오.

    • ~이다 dr__blackburn 다른 dr_blackburn?
    • ~이다 dr__blackburn 다른 mr__blackburn?
    • 주요 숫자가 의미가 있습니까?
    • 선도/후행은 의미가 있습니까?
    • 등.
  2. 이름을 디렉토리로 변환하기위한 규칙과 알고리즘을 생각해보십시오 (Leon 's는 아주 좋은 시작입니다)

  3. 이름으로 읽고 한 번에 하나씩 처리하십시오.

    • 나는 opendir와 재귀의 조합을 사용할 것입니다
    • 나는 당신이 그들을 처리 할 때 그것들을 복사 할 것입니다. 다시 Leon의 게시물이 좋은 예입니다
  4. 이 스크립트를 미래에 유지하고 사용해야한다면, 나는 진정으로 테스트를 만들 것입니다 (예 : http://search.cpan.org/dist/test-more/) 각 regexp 경로에 대해; 새로운 주름을 찾으면 새로운 테스트를 추가하고 실패한 지 확인한 다음 Regex를 고치고 테스트를 다시 실행하여 아무것도 파손되지 않도록하십시오.

나는 한동안 Perl을 사용하지 않았으므로 Ruby에 이것을 쓸 것입니다. 의사 코드를 설정하기 위해 언급하겠습니다.

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" 이 모든 파일 이름에 대해서는 두 번째로 줄어든 것이 장소에서 이름이 틀린 동일한 사람과 비슷해야합니다 (예 : "Brian Jones"로 변경). 당신은 일종의 사용을 원할 수도 있습니다 거리를 편집합니다 비교할 유사성 지표로 @tokens[-2] 다양한 파일 이름의 경우; 두 개의 항목에 충분한 성이 비슷한 경우, 합병 후보자로 자극해야합니다.

당신이 묻는대로 매우 일반 질문, 모든 언어는 우리가 규칙을 더 잘 체계화하는 한 이것을 할 수 있습니다. 우리는조차 없습니다 세부 사항, "샘플"만.

따라서 맹인으로 일하면 인간 모니터링이 필요한 것처럼 보입니다. 그래서 아이디어는 a입니다 . 반복적으로 실행하고 확인하고 다시 실행하고 몇 가지 작은 수동 작업에 모든 것을 정렬 할 때까지 계속해서 확인할 수있는 것입니다.

아래 코드는 만듭니다 많은 가정, 당신은 그것을 처리하기 위해 우리에게 거의 남겨 두었 기 때문에. 그 중 하나는 샘플이 가능한 모든 성의 목록이라는 것입니다. 다른 성이 있으면 'EM을 추가하고 다시 실행하십시오.

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 
                             )
        );
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top