다운받은 깨진 한글 파일 이름 복구하기

Mon, 23 Jul 2012 19:04

Updated: 2018-03-31 18:50

인터넷에서 웹 브라우저로 파일을 받으면 서버 측의 잘못된 설정으로 인하여 한글 파일 이름이 이상하게 되는 경우가 많다.

cp949 코드가 utf-8 로 둔갑된 경우

사용자 컴퓨터 환경이 utf-8 환경이라면 그 파일 이름 자체가 utf-8 이기 때문에 iconv, convmv 로도 복구가 안 된다.
이럴 경우 아래처럼 하면 복구가 된다.
cp949(uhc)와 euc-kr 은 서로 다른 코드이다. euc-kr ⊂ cp949 이다. cp949는 euc-kr을 확장한 코드이다.

# coding: utf-8
# irb 에서 다음을 입력하면 한글이 정상적으로 표시되는 것을 알 수 있다. 
"ÇÁ·Î±×·¡¹Ö¾ð¾î·Ð".unpack("U*").pack("C*").force_encoding("euc-kr").encode("utf-8") #=> "프로그래밍언어론"

"ÇÁ·Î±×·¡¹Ö¾ð¾î·Ð".unpack("U*").pack("C*").force_encoding("cp949").encode("utf-8") #=> "프로그래밍언어론"

# 아래 함수(또는 메소드)를 이용하여 프로그램을 작성하면 된다.
def repair_cp949 utf8
    utf8.unpack("U*").pack("C*").force_encoding("cp949").encode("utf-8")
end

repair_cp949 "ÇÁ·Î±×·¡¹Ö¾ð¾î·Ð" #=> "프로그래밍언어론"

cp949 코드가 URL 인코딩된 상태로 다운로드된 경우

URL 인코딩된 파일 이름으로 다운로드되는 경우도 많다.
%B9%AB%B7%E1%C0%DA%B7%E14--SRS--%B5%B6%C7%D8%BA%F1%B9%FD(%B4%DC%B6%F4%B1%B8%C1%B6)%C0%E5%B9%AE%B5%B6%C7%D8.doc 이런 파일 이름이 URL 인코딩된 파일 이름이다.
참고 링크: http://en.wikipedia.org/wiki/Percent-encoding
이러한 파일 이름을 복구해보자.

irb를 열고 다음처럼 입력해본다.

irb(main):001:0> require 'uri'
=> true
irb(main):002:0> URI.unescape("%B9%AB%B7%E1%C0%DA%B7%E14--SRS--%B5%B6%C7%D8%BA%F1%B9%FD(%B4%DC%B6%F4%B1%B8%C1%B6)%C0%E5%B9%AE%B5%B6%C7%D8").unpack("C*").pack("U*")
=> "¹«·áÀÚ·á4--SRS--µ¶Çغñ¹ý(´Ü¶ô±¸Á¶)Àå¹®µ¶ÇØ"

위에서 설명한 ÇÁ·Î±×·¡¹Ö¾ð¾î·Ð 이러한 형태의 문자열이 출력되었다. 아래처럼 하면 사람이 알아볼 수 있는 정상적인 utf-8 문자열이 출력된다.

irb(main):026:0> URI.unescape("%B9%AB%B7%E1%C0%DA%B7%E14--SRS--%B5%B6%C7%D8%BA%F1%B9%FD(%B4%DC%B6%F4%B1%B8%C1%B6)%C0%E5%B9%AE%B5%B6%C7%D8").force_encoding("cp949").encode("utf-8")
=> "무료자료4--SRS--독해비법(단락구조)장문독해"

URL 인코딩된 깨진 한글 파일 이름을 고치는 메소드를 만들어보자.

require 'uri'

def repair_url_encoded_cp949 url_encoded_string
    URI.unescape(url_encoded_string).force_encoding("cp949").encode("utf-8")
end

repair_url_encoded_cp949 "%B9%AB%B7%E1%C0%DA%B7%E14--SRS--%B5%B6%C7%D8%BA%F1%B9%FD(%B4%DC%B6%F4%B1%B8%C1%B6)%C0%E5%B9%AE%B5%B6%C7%D8"
    #=> "무료자료4--SRS--독해비법(단락구조)장문독해"

아래는 디렉토리 내의 파일 이름을 고치는 소스이다.

# coding: utf-8

def repair_cp949 utf8
    begin
        utf8.unpack("U*").pack("C*").force_encoding("cp949").encode("utf-8")
    rescue Encoding::InvalidByteSequenceError
        # FIXME
        utf8
    end
end

def repair_recursive dir
    dirent = Dir.entries(dir) - [".", ".."]
    dirent.each do |path|
        if File.directory? path
            path2 = repair_cp949(path)
            `mv "#{path}" "#{path2}"` if path != path2
            Dir.chdir path2
            repair_recursive "."
            Dir.chdir ".."
        elsif File.file? path
            path2 = repair_cp949(path)
            `mv "#{path}" "#{path2}"` if path != path2
        end
    end
end

if ARGV.length.zero?
    repair_recursive "."
else
    repair_recursive ARGV[0]
end

seungwon0 2011-02-01 22:08

좋은 글 잘 읽었습니다.

이제부터는 한글 파일명이 깨지는 문제 때문에 고생할 일은 없겠군요.

같은 작업을 저는 Perl로 시도해봤습니다.

% perl -Mutf8 -MEncode -le 'print encode_utf8 decode "cp949", "ÇÁ·Î±×·¡¹Ö¾ð¾î·Ð"'
프로그래밍언어론
% perl -MEncode -MURI::Escape -le 'print encode_utf8 decode "cp949", uri_unescape "%B9%AB%B7%E1%C0%DA%B7%E14--SRS--%B5%B6%C7%D8%BA%F1%B9%FD(%B4%DC%B6%F4%B1%B8%C1%B6)%C0%E5%B9%AE%B5%B6%C7%D8"'
무료자료4--SRS--독해비법(단락구조)장문독해