[질문] ls를 흉내내고 싶은데..

blue621의 이미지

ls를 흉내내는 프로그램을 만들고 싶은데요..ㅎㅎ;;

ls의 기능에다가 서브 디렉토리 까지 순회할려구 하는데..

chdir을 어떻게 사용해야 할지..;;

간단한 코드좀 알려주시면 감사하겠습니다^^;;

서브 디렉토리 순회하는 것만;;

그럼 즐거운 하루 되세요 ^-^

cdpark의 이미지

ls -R

옵션이 있습니다만..

blue621의 이미지

ls -R 말구..; chdir을 이용해서 순회하는 프로그램을 만드려는데..

대충 어떻게 하면 되는지..

코드를 알고 싶어서요..^^;;

alwaysrainy의 이미지

재귀 함수를 사용하면 간단할 듯 ^^;

---------------------------------------
세계는 넓고, 할일은 많다.

cdpark의 이미지

find -type d -exec ls {} \;

이건요?

blue621의 이미지

많으신 분들이 답변을 달아주시니..;

감사할 따릅입니다^^;;

그런데.. 제가 하려는 것은..

쉘 프로그래밍이 아니라..

C 코드 입니다;;

ㅎㅎ;;

재귀로 하면 될 듯 한데..

어떤식으로 해야

상위 디렉토리 하위디렉토리를 왔다 갔다 할 수 있을까요 ㅎㅎ;

간단한 코드를 보여주심이 ㅜㅡㅜ;

Necromancer의 이미지

시스템 콜 중에서 파일시스템에 관련된 부분을 알아보시기 바랍니다.
아마 이정도면 충분할듯 싶네요.

chdir() -> 작업 디렉토리 변경
getdirent() -> 현 디렉토리내에 있는 파일 리스트 얻기 (이 함수이름 맞나?)
stat() -> 파일의 정보 얻기

Written By the Black Knight of Destruction

cinsk의 이미지

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>

#define DIR_SEPARATOR	"/"

/* 
 * Callback prototype for dir_traverse.
 *
 * If the callback returns -1, dir_traverse stop traversing, 
 * return immediately.  If the callback returns 0, dir_traverse stop calling
 * itself (recursion) for that directory. If the callback received 
 * non-directory filename, return value 0 is the same as return value 1.
 * If the callback returns 1, dir_traverse works normally.
 *
 * Note that callbacks never receive "." and ".." as its argument.
 */
typedef int (*visit_t)(const char *pathname);

int dir_traverse(const char *pathname, visit_t func);
int is_dir(const char *pathname);

int print_name(const char *pathname);

int
main(int argc, char *argv[])
{
  if (argc != 2) {
    fprintf(stderr, "usage: %s DIR\n", argv[0]);
    return 1;
  }

  dir_traverse(argv[1], print_name);
  return 0;
}

int
print_name(const char *pathname)
{
  printf("%s\n", pathname);
  return 0;
}

int
dir_traverse(const char *pathname, visit_t func)
{
  char *p;
  int len, ret;
  struct dirent *ent;
  DIR *dir;

  p = malloc(pathconf(pathname, _PC_PATH_MAX) + 1);
  if (!p)
    return -1;

  strcpy(p, pathname);
  len = strlen(p);
  if (p[len - 1] != DIR_SEPARATOR[0]) {
    strcpy(p + len, DIR_SEPARATOR);
    len++;
  }

  dir = opendir(pathname);
  if (!dir) {
    free(p);
    return -1;
  }
  while ((ent = readdir(dir)) != NULL) {
    if (strcmp(ent->d_name, ".") == 0 ||
        strcmp(ent->d_name, "..") == 0)
      continue;
    strcpy(p + len, ent->d_name);

    ret = func(p);

    if (ret > 0 && is_dir(p))
      dir_traverse(p, func);
  }
  closedir(dir);
  free(p);
  return 0;
}

int
is_dir(const char *pathname)
{
  struct stat statbuf;
  
  if (stat(pathname, &statbuf) == -1)
    return 0;
  return S_ISDIR(statbuf.st_mode);
}
lunarainbow의 이미지

음. 제가 잘못 해석한 것인지는 모르겠지만,

cinsk 님의 코드에 버그 하나.. ^^;;

int
print_name(const char *pathname)
{
  printf("%s\n", pathname);
  return 0;
}

    ret = func(p);

    if (ret > 0 && is_dir(p))
        dir_traverse(p, func);

여기서 func는 함수 포인터로써, print_name을 실행하게 됨.

이렇게 되면, print_name 은 항상 0만 리턴하구, 결국 순환을 안하게 되는거 같은데... 맞는지 확인해 주세요

if ( is_dir(p) )
  dir_traverse(p, func);

이렇게 해줘야 될 것 같아요. :wink:

cinsk의 이미지

(주석을 달았습니다만) 버그는 아닙니다.

다만 print_name이 1을 리턴하도록 예제를 만드는게 좋을 거 같군요.

print_name이 -1을 리턴하면 dir_traverse 즉시 종료,
0을 리턴하면 그 때 인자로 들어왔던 directory에 대해 recursion 안함,
1을 리턴하면 계속 recursive하게 탐색.

하게 했던 것이죠. :wink:

lunarainbow의 이미지

아하. 주석이 영어라서 안읽었었는데, 거기 있었군요! :D

그런데 "." 이랑 ".." 이랑은 굳이 strcmp 같은걸루 비교하는 수밖에 없는 것인가요?

저두 지난번에 누군가 물어보길래, 대충 짜서 주긴 했는데,

마땅히 "." 이랑 ".."를 처리할 방법이 떠오르질 않아서 그냥 strcmp 썼었는데..

지금 보니깐 cinsk 님도 그냥 strcmp 사용하셨네요..

정말 그 방법이외엔 불가능 한 것일가요?? :cry:

둘다 디렉토리긴 하지만... 뭔가 방법이 있을것도 같은데..

cinsk의 이미지

lunarainbow wrote:
아하. 주석이 영어라서 안읽었었는데, 거기 있었군요! :D

그런데 "." 이랑 ".." 이랑은 굳이 strcmp 같은걸루 비교하는 수밖에 없는 것인가요?

저두 지난번에 누군가 물어보길래, 대충 짜서 주긴 했는데,

마땅히 "." 이랑 ".."를 처리할 방법이 떠오르질 않아서 그냥 strcmp 썼었는데..

지금 보니깐 cinsk 님도 그냥 strcmp 사용하셨네요..

정말 그 방법이외엔 불가능 한 것일가요?? :cry:

둘다 디렉토리긴 하지만... 뭔가 방법이 있을것도 같은데..

글쎄여? 구체적으로 어떤 것을 원하시는지... strcmp 같은 함수를 쓰지 않고 다른 방법을 원하신다는데.. strcmp를 써서 할 때 무엇이 문제가 되는지 알려주시면 고맙겠군요.

속도가 걱정이 되시는 건지? 아니면 뭔가 다른 문제가 있나요?

lunarainbow의 이미지

음.. 굳이 이유를 대라면.. 속도??

그치만 궁극적인 이유로는,

이쁠꺼 같아서.. 라고 하면 될런지 :wink:

왠지...

if ( strsmp(.....

이렇게 나간다는게 맘에 안드는군요. ^^

별로 눈이 높진 않지만, 그래도 이쁜걸 좋아하는게 대부분 사람들의 본능아닐까요? ㅎㅎ

jemiro의 이미지

NAME
ftw, nftw - file tree walk

SYNOPSIS
#include <ftw.h>

int ftw(const char *dir, int (*fn)(const char *file, const struct stat
*sb, int flag), int nopenfd);

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.