2013-06-18 2 views
2

디렉토리에있는 파일의 목록을 다음 있습니다 :Windows의 Perl이 움라우트로 파일의 이름을 바꿀 수없는 이유는 무엇입니까?

  1. 01 년생 - 칭찬 - Kissed.flac
  2. 02 Wunschkind.flac
  3. 이에 it.flac
  4. 04 아래있어
  5. 03 Hole.flac
  6. 05 Wälsungenblut.flac
  7. ... N. 0N 파일 이름

# 예, 다음은 Oomph의 노래입니다!

펄에

및 다음 프로그램 :

디렉토리의 목록을 가져옵니다 및 번호 뒤에 점을 추가하여의 파일 이름을 변경
use warnings; 
use strict; 
use utf8; 
use open qw(:encoding(UTF-8) :std); 

my @dirnames; 

while ((my $dirname = <>) =~ /\S/) { 
    chomp($dirname); 
    push (@dirnames, $dirname); 
} 

foreach my $dirname (@dirnames) { 
    opendir (DIR, $dirname); 
    while (my $file = readdir(DIR)) { 
     if(length($file)>5) { 
      print $file , "\n"; 
      my $newfile; 

      $newfile = substr($file, 0, 2); 
      $newfile .= '.'; 
      $newfile .= substr($file, 2); 

      rename ($dirname . '\\' . $file, $dirname . '\\' . $newfile) or die $!; 
     } 
    } 
    closedir DIR; 
} 

.

프로그램이 모든 파일에서 올바르게 작동하지만 파일 이름에 움라우트가 포함 된 파일의 이름을 바꿀 때 Windows PowerShell과 명령 줄 모두 Permission denied의 기능에 오류가 발생합니다.

이 문제를 해결하는 방법은 무엇입니까?

UPD. 소프트웨어 :

  • 윈도우 8 64
  • 은 ActiveState의 ActivePerl의 1601 (펄 5.16)
+0

당신이 사용하는 데이터'의 출력을 제공시겠습니까 :: 덤퍼를; $ 데이터 :: 덤퍼 :: Useqq = 1; print (Dumper ($ file));'그래서 우리는 우리의 대답에 조금 집중할 수 있습니다. – ikegami

+0

@ikegami 결과는 $ VAR1 = "01. Born - Praised - Kissed.flac"; 01. 출생 - 칭찬 - Kissed.flac $ VAR1 = "02 .. Wunschkind.flac"; 02 .. Wunschkind.flac $ VAR1 = "03 .. 너 그거야 .flac"; 03 .. 당신은 그것을 가지고 있습니다 .flac $ VAR1 = "04 ..이 구멍 아래로 .flac"; 04.이 구멍 아래로 .flac $ VAR1 = "05. W? lsungenblut.flac"; 05. W? lsungenblut.flac e : \ rename.pl 줄 20, <> 줄 2에서 사용 권한이 거부되었습니다. – llvk

+0

아마도 '사용 권한이 거부되었습니다.' :) –

답변

3

Perl의 readdir은 유닉스 유산으로 인한 파일 이름 만 처리 할 수 ​​있기 때문에 레거시 인터페이스 ("ANSI")를 사용합니다.

"ANSI"인터페이스는 코드 페이지라고하는 1 바이트 문자 인코딩을 사용합니다. 시스템의 코드 페이지는 1251이며 "ä"인코딩 방법을 제공하지 않으므로 "ä"가 포함 된 파일 이름은 readdir에 의해 반환 될 수 없습니다.

이 "ANSI"인터페이스 (FindFirstFileA)는 피해야하고 FindFirstFileW에 액세스해야합니다. 그러면 파일 이름이 UTF-16le로 제공되고 Win32API::FileMoveFileExW으로 전달할 수 있습니다. Win32::Unicode::Diropen + fetch은 그렇게합니다.

음침한 상태입니다. 나는 그것을 다루는 의미 였지만 광범위한 프로젝트가 될 것입니다.

use utf8; 
use Win32 qw(); 
BEGIN { 
    binmode(STDOUT, ':encoding(cp'.Win32::GetConsoleOutputCP().')'); 
    binmode(STDERR, ':encoding(cp'.Win32::GetConsoleOutputCP().')'); 
} 

use strict; 
use warnings; 
use feature qw(say); 
use open ':encoding(UTF-8)'; 

use Encode    qw(encode); 
use Win32::Unicode::Dir qw(mvtreeW); 
use Win32API::File  qw(MoveFileExW); 

my $dir_qfn = '.'; 

my $wdir = Win32::Unicode::Dir->new(); 
$wdir->open($dir_qfn) 
    or die("Can't open $dir_qfn: ".$wdir->error()); 

for ($wdir->fetch()) { 
    next if /^\.\.?\z/; 
    next if length() <= 5; 

    say; 

    my $o_fn = $_; 
    s/^..\K/./s; 
    my $n_fn = $_; 

    MoveFileExW(
     encode('UTF-16le', "$dir_qfn/$o_fn\0"), 
     encode('UTF-16le', "$dir_qfn/$n_fn\0"), 
     0, # or MOVEFILE_REPLACE_EXISTING 
    ) 
     or die("Can't rename $o_fn to $n_fn: $^E\n"); 
} 

$wdir->close(); 
+0

내 대답 업데이트. – ikegami

+0

감사합니다. 내 시간을 저장했습니다. – llvk

0

는 UTF-8 것처럼 당신은 디렉토리를 읽고,하지만 당신은 윈도우 1252에서 정말 부호화. use open qw(...)가 없어지면 작동합니다.

+0

1 시간 전에이 방법을 시도했습니다. 결과가 없다. 당신은 당신의 컴퓨터에서 그것을 시험해 볼 수 있습니까? – llvk

+0

"디렉토리를 UTF-8처럼 읽는 중입니까?" 아니요. '열린 상태로 사용'은 최소한 readdir에 영향을주지 않습니다. – ikegami

+0

방금 ​​했어 - 여기서 일 했어! 내가 'open open'을 떠날 때, "j : um.pl line 24, <> line 2에 그런 파일이나 디렉토리가 없다" 오류 메시지 ...하지만 나가면 그것을 디렉터리의 모든 파일의 이름을 바꿉니다. stdin이나 파일에서 의견을 받고 있습니까? 입력은 어떤 인코딩입니까? – Massa

-2

"rename.pl"에 대한 액세스 권한이 있습니까? 할 수 있어요

perl rename.pl "s/^(\d\d)/$1./" *flac 

?

+0

s/^ (\ d \ d) /./을 열 수 없습니다. e : \ rename.pl 줄에 해당 파일이나 디렉토리가 없습니다. 11. 패턴 일치 (m //)에서 초기화되지 않은 값 $ dirname 사용 전자 : \ rename.pl 라인 11. – llvk

+0

나는 ** 다른 ** rename.pl, 미안해에 대해 미안 ... http://search.cpan.org/~rmbarker/File-Rename-0.06/rename .PL – Massa

+0

이 rename.pl 않습니다 : 'mkdir s/^ (; mkdir s/^ (\ d; mkdir s/^ (\ d \ d); c : \ rename.pl s 열 수 없습니다 /^(\d\d)/./ : 해당 파일이나 디렉토리가 없습니다. ' – llvk

관련 문제