[질문]C code : 하위폴더에 있는 모든 euc-kr 파일을 utf-8으로 바꾸기

ahsan의 이미지

안녕하세요
예전에 clique님이 알려주신 nftw 함수를 이용해서
하위폴더를 다 뒤져서 모든 euc-kr 파일을 utf-8으로 변환하는 코드를 써봤습니다.
그러나 기대한 것처럼 되지가 않네요.(컴파일되고, traverse 되지만 변환이 안됩니다.)
고수님들의 도움을 부탁드립니다.

#define _XOPEN_SOURCE 500  
#include<stdio.h>
#include<stdlib.h>
#include<ftw.h>            // 디렉토리 순환함수
#include<string.h>
#include<iconv.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
 
int euc_to_utf(const char *fpath)
{
   iconv_t cd = iconv_open("UTF-8", "EUC-KR");
   if(cd == (iconv_t)(-1))
   {
      perror("iconv_open :");
      return -1;
   }
 
   char inBuf[BUFSIZE];
   char outBuf[BUFSIZE*2];
   int inBufSize = sizeof(inBuf);
   int outBufSize = sizeof(outBuf);
   memset(outBuf, 0, outBufSize);
 
   int inFd = open(fpath, O_RDWR);
   if(inFd == -1)
   {
      perror("Input file : ");
      return -1;
   }
 
   int outFd = open(fpath, O_WRONLY | O_CREAT);
   if(outFd == -1)
   {
      perror("Output file : ");
      return -1;
   }
 
   size_t readBytes = read(inFd, inBuf, sizeof(inBuf));
   inBuf[readBytes] = '\0';
 
   // file convert
   size_t writeBytes = sizeof(outBuf);
   char* in = inBuf;
   char* out = outBuf;
   if(iconv(cd, &in, &readBytes, &out, &writeBytes) == -1) {
      printf("Failed to iconv errno: %d  EILSEQ: %d\n", errno, EILSEQ);
      exit(-1);
   } else {
      outBuf[writeBytes] = '\0';
      write(outFd, outBuf, writeBytes);
      close(outFd);
   }
   close(inFd);
 
   return 0;
}
 
static int conver_helper(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf)
{
   switch(tflag)
   {
      case FTW_D:          // fpath is a directory
      case FTW_DP:         // All of the files and subdirectories whithin fpath have been processed
         if(euc_to_utf(fpath) == -1)
            printf("파일변환 실패 ! ");
         break;
      case FTW_F:          // fpath is normal file
      case FTW_SL:         // fpath is symbolic link, and FTW_PHYS was set in flags
      default:
         puts("do nothing");
   }
   return 0;
}
 
int main(int argc, char** argv)
{
   const char* file_to_conv = ".";
   int flags = 0;
   flags |= FTW_DEPTH;// post-order traverse
 
   if(argc == 2)
      file_to_conv = argv[1];
 
   if(nftw(file_to_conv, conver_helper, 10, flags) == -1)
   {
      perror("nftw");
      exit(EXIT_FAILURE);
   }
 
   return 0;
}

cinsk의 이미지

open(2)의 첫 인자가 겹치네요. 그런데 궂이 이렇게 C 프로그램을 작성할 이유가 있나요?

저라면 그냥 shell에서 실행할 것 같네요.

$ find . -type f -exec cp949-utf8.sh {} \;

cp949-utf8.sh는 아래 정도로..

#!/bin/sh
 
TMP=/tmp
tmpfile=$TMP/iconv.$$
 
trap "rm -f $tmpfile" HUP INT QUIT TERM
 
for f in "$@"; do
    iconv -f cp949 -t utf-8 "$f" >$tmpfile
    if $? -eq 0; then
        mv -f $tmpfile "$f"
    fi
done
rm -f $tmpfile

--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/

ahsan의 이미지

안녕하세요. 쉘스크립트까지 작성해 주시다니
답변 감사합니다.

제가 질문을 올린 이유는 nftw함수를 재대로 이해하지 못해서입니다.
어떻게 사용되는지 궁금해서 가르침을 부탁드린것입니다.
선생님께서는 input과 output에서 open의 파일인자가 같은 것을 염려하셨는데
제가 따로이 테스트를 해 보았기 때문에 이 부분은 전혀 상관이 없습니다.

쉘코드에 인터럽터 처리까지 하시는 것을 보니 무척 세심한 배려를 하셨네요.
사려깊은 가르침에 감사드립니다.

ahsan의 이미지

제가 선생님께서 작성하신 쉘스크립트을 테스트해 본 결과 스크립트에는
이상이 없는데 find의 검색값이 재대로 전달이 안되나 봅니다.
그래서 제가 스크립트를 약간 수정을 했습니다.

#!/bin/sh
 
TMP=/tmp
tmpfile=$TMP/iconv.$$
tmpname=$TMP/file.txt
 
find . -name "*.html" > $tmpname
 
limit=`cat $tmpname | wc -l`;
filename=(`awk '{print $1}' $tmpname`);
 
for((i=0; i<$limit; i++))
do
        iconv -f cp949 -t utf-8 ${filename[i]} > $tmpfile
        if [ $? -eq 0 ]
        then
                mv -f $tmpfile "${filename[i]}"
        fi
done
rm -f $tmpfile
rm -f $tmpname

쉘스크립트에서 C style의 for문을 지원해 주어서 다행입니다.
반복순환을 for나 while로 생각하는것이 저에게는 재일 편합니다.
이런 경우 Python이나 Ruby에서는 어떻게 구현하는지 궁금하네요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.