免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 9340 | 回复: 19
打印 上一主题 下一主题

Linux 遍历目录有没有什么好方法? [复制链接]

论坛徽章:
27
处女座
日期:2016-04-18 14:00:4515-16赛季CBA联赛之福建
日期:2023-03-31 15:54:2315-16赛季CBA联赛之深圳
日期:2020-06-02 10:10:5015-16赛季CBA联赛之广夏
日期:2019-07-23 16:59:452016科比退役纪念章
日期:2019-06-26 16:59:1315-16赛季CBA联赛之天津
日期:2019-05-28 14:25:1915-16赛季CBA联赛之青岛
日期:2019-05-16 10:14:082016科比退役纪念章
日期:2019-01-11 14:44:062016科比退役纪念章
日期:2018-07-18 16:17:4015-16赛季CBA联赛之上海
日期:2017-08-22 18:18:5515-16赛季CBA联赛之江苏
日期:2017-08-04 17:00:4715-16赛季CBA联赛之佛山
日期:2017-02-20 18:21:13
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-06-01 17:27 |只看该作者 |倒序浏览
网上搜索了一堆,都是递归遍历目录的,有没有非递归的方式?

另外

  1. /*
  2. * 程序名: C语言遍历目录并输出目录内所有文件名
  3. * 作者:        Yucoat(www.yucoat.com)
  4. * 时间:        2011-10-5
  5. * 描述:        遍历目录,输出非隐藏文件的文件名并遍历目录内的子目录
  6. */
  7. #include <dirent.h>
  8. #include <sys/stat.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>

  11. /*输出空格,为了能够让输出结果用层次感,使用这个函数输出空格,其中deepth代表层*/
  12. void printfspace(int deepth);

  13. /*遍历函数directory代表目录的路径,deepth代表目录的深度*/
  14. void scan_dir(const char *directory, int deepth);

  15. /*主函数*/
  16. int main(int argc, char *argv[])
  17. {
  18.     int deepth = 0;
  19.     if (argc != 2)
  20.     {
  21.         printf("Error!nUsage:%s pathn", argv[0]);
  22.         return 1;
  23.     }
  24.     scan_dir(argv[1], deepth);
  25.     return 0;
  26. }


  27. void printfspace(int deepth)
  28. {
  29.     int temp = 0;
  30.     while (temp < deepth)
  31.     {
  32.         printf("    ");
  33.         temp++;
  34.     }
  35. }


  36. void scan_dir(const char *directory, int deepth)
  37. {
  38.     DIR *dp;
  39.     struct dirent *entry;
  40.     struct stat statbuf;
  41.    
  42.     if((dp = opendir(directory)) == NULL)
  43.     {
  44.         perror("opendir");
  45.         return;
  46.     }
  47.     chdir(directory);

  48.     while ((entry = readdir(dp)) != NULL)
  49.     {
  50.         lstat(entry->d_name, &statbuf);
  51.         if (S_ISDIR(statbuf.st_mode))
  52.         {

  53.             if ((strcmp(entry->d_name, ".") != 0) &&
  54.                     (strcmp(entry->d_name, "..") != 0) &&
  55.                     (entry->d_name[0] != '.'))
  56.             {
  57.                 printfspace(deepth);
  58.                 printf("%s/n", entry->d_name);
  59.                 scan_dir(entry->d_name, (deepth+1));
  60.             }
  61.         }
  62.         else
  63.         {
  64.             if (entry->d_name[0] != '.')
  65.             {
  66.                 printfspace(deepth);
  67.                 printf("%sn", entry->d_name);
  68.             }
  69.         }
  70.     }
  71.     chdir("..");
  72.     closedir(dp);
  73. }
复制代码
chdir 这样的方式会改变工作目录 有没有什么办法不调用 chdir 遍历呢?

论坛徽章:
0
2 [报告]
发表于 2012-06-01 17:28 |只看该作者
你平时都不观注 cu的吗?

论坛徽章:
0
3 [报告]
发表于 2012-06-01 17:29 |只看该作者
本帖最后由 三月廿七 于 2012-06-01 17:31 编辑

我对你的视力表示怀疑,
对了,我上次写的是 windows下的, 可能会有很大区别

论坛徽章:
0
4 [报告]
发表于 2012-06-01 17:30 |只看该作者
一件事情有合适的方法去做,却非要徒劳无功的言其他。

论坛徽章:
0
5 [报告]
发表于 2012-06-01 17:32 |只看该作者
本帖最后由 三月廿七 于 2012-06-01 17:34 编辑
walleeee 发表于 2012-06-01 17:30
一件事情有合适的方法去做,却非要徒劳无功的言其他。

可能是没有真正理解 dfs,不想囫囵吞枣的用吧,
要不然不会问, 问了就说明不会

论坛徽章:
2
技术图书徽章
日期:2013-09-04 15:21:51酉鸡
日期:2013-11-01 21:20:20
6 [报告]
发表于 2012-06-01 17:47 |只看该作者
就是树的遍历嘛!

论坛徽章:
0
7 [报告]
发表于 2012-06-01 17:51 |只看该作者
  1. #include <Windows.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. typedef void (*Callback)(const char *path, const WIN32_FIND_DATA *info, void *arg);

  5. void PrintPath(const char *path, const WIN32_FIND_DATA *info, void *arg)
  6. {
  7.     printf("%s\n", info->cFileName);
  8. }

  9. void RecursiveDirectory(const char *path, Callback callback, void *arg)
  10. {
  11.     WIN32_FIND_DATA fd;
  12.     HANDLE hd = INVALID_HANDLE_VALUE;

  13.     hd = FindFirstFile(path, &fd);
  14.     if(hd == INVALID_HANDLE_VALUE)
  15.     {
  16.         return ;
  17.     }

  18.     do
  19.     {
  20.         callback(path, &fd, arg);

  21.         if((fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, ".."))
  22.         {
  23.             char subpath[MAX_PATH] = {'\0'};
  24.             sprintf(subpath, "%s\\%s\\*", path, fd.cFileName);
  25.             RecursiveDirectory(subpath, callback, arg);
  26.         }

  27.     } while(FindNextFile(hd, &fd));

  28.     FindClose(hd);
  29. }

  30. int main(int argc, char **argv)
  31. {
  32.     if(argc > 1)
  33.     {
  34.         RecursiveDirectory(argv[1], PrintPath, NULL);
  35.     }

  36.     return 0;
  37. }
复制代码
很久之前的一个框,有用就看吧。
*nix的*dir系列函数比win的Find*系列函数好用多了。

论坛徽章:
0
8 [报告]
发表于 2012-06-01 17:53 |只看该作者
walleeee 发表于 2012-06-01 17:51
很久之前的一个框,有用就看吧。
*nix的*dir系列函数比win的Find*系列函数好用多了。


walleeee  的代码看着果然赏心悦目啊

论坛徽章:
0
9 [报告]
发表于 2012-06-01 17:58 |只看该作者
回复 8# 三月廿七


win的Find*系函数就是畸形,列目录非要通配符,你说蛋疼不蛋疼,远远没有*nix的dir系列函数好用。

  1. #include <windows.h>
  2. #include <tchar.h>
  3. #include <stdio.h>
  4. #include <strsafe.h>
  5. #pragma comment(lib, "User32.lib")

  6. void DisplayErrorBox(LPTSTR lpszFunction);

  7. int _tmain(int argc, TCHAR *argv[])
  8. {
  9.    WIN32_FIND_DATA ffd;
  10.    LARGE_INTEGER filesize;
  11.    TCHAR szDir[MAX_PATH];
  12.    size_t length_of_arg;
  13.    HANDLE hFind = INVALID_HANDLE_VALUE;
  14.    DWORD dwError=0;
  15.    
  16.    // If the directory is not specified as a command-line argument,
  17.    // print usage.

  18.    if(argc != 2)
  19.    {
  20.       _tprintf(TEXT("\nUsage: %s <directory name>\n"), argv[0]);
  21.       return (-1);
  22.    }

  23.    // Check that the input path plus 3 is not longer than MAX_PATH.
  24.    // Three characters are for the "\*" plus NULL appended below.

  25.    StringCchLength(argv[1], MAX_PATH, &length_of_arg);

  26.    if (length_of_arg > (MAX_PATH - 3))
  27.    {
  28.       _tprintf(TEXT("\nDirectory path is too long.\n"));
  29.       return (-1);
  30.    }

  31.    _tprintf(TEXT("\nTarget directory is %s\n\n"), argv[1]);

  32.    // Prepare string for use with FindFile functions.  First, copy the
  33.    // string to a buffer, then append '\*' to the directory name.

  34.    StringCchCopy(szDir, MAX_PATH, argv[1]);
  35.    StringCchCat(szDir, MAX_PATH, TEXT("\\*"));

  36.    // Find the first file in the directory.

  37.    hFind = FindFirstFile(szDir, &ffd);

  38.    if (INVALID_HANDLE_VALUE == hFind)
  39.    {
  40.       DisplayErrorBox(TEXT("FindFirstFile"));
  41.       return dwError;
  42.    }
  43.    
  44.    // List all the files in the directory with some info about them.

  45.    do
  46.    {
  47.       if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  48.       {
  49.          _tprintf(TEXT("  %s   <DIR>\n"), ffd.cFileName);
  50.       }
  51.       else
  52.       {
  53.          filesize.LowPart = ffd.nFileSizeLow;
  54.          filesize.HighPart = ffd.nFileSizeHigh;
  55.          _tprintf(TEXT("  %s   %ld bytes\n"), ffd.cFileName, filesize.QuadPart);
  56.       }
  57.    }
  58.    while (FindNextFile(hFind, &ffd) != 0);

  59.    dwError = GetLastError();
  60.    if (dwError != ERROR_NO_MORE_FILES)
  61.    {
  62.       DisplayErrorBox(TEXT("FindFirstFile"));
  63.    }

  64.    FindClose(hFind);
  65.    return dwError;
  66. }


  67. void DisplayErrorBox(LPTSTR lpszFunction)
  68. {
  69.     // Retrieve the system error message for the last-error code

  70.     LPVOID lpMsgBuf;
  71.     LPVOID lpDisplayBuf;
  72.     DWORD dw = GetLastError();

  73.     FormatMessage(
  74.         FORMAT_MESSAGE_ALLOCATE_BUFFER |
  75.         FORMAT_MESSAGE_FROM_SYSTEM |
  76.         FORMAT_MESSAGE_IGNORE_INSERTS,
  77.         NULL,
  78.         dw,
  79.         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  80.         (LPTSTR) &lpMsgBuf,
  81.         0, NULL );

  82.     // Display the error message and clean up

  83.     lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
  84.         (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
  85.     StringCchPrintf((LPTSTR)lpDisplayBuf,
  86.         LocalSize(lpDisplayBuf) / sizeof(TCHAR),
  87.         TEXT("%s failed with error %d: %s"),
  88.         lpszFunction, dw, lpMsgBuf);
  89.     MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);

  90.     LocalFree(lpMsgBuf);
  91.     LocalFree(lpDisplayBuf);
  92. }
复制代码
这是msdn的例子,看完有没有恶心啊?

   // Check that the input path plus 3 is not longer than MAX_PATH.
   // Three characters are for the "\*" plus NULL appended below.

   // Prepare string for use with FindFile functions.  First, copy the
   // string to a buffer, then append '\*' to the directory name.

是不是看完就要吐了?
还有MAX_PATH,根本就不行嘛,什么256个字符,坑爹么?ntfs一个文件名就1-256字符,难道路径都不见了?没层次了?

TCHAR szDir[MAX_PATH];

这不就是典型的坑爹代表么?

论坛徽章:
0
10 [报告]
发表于 2012-06-01 18:01 |只看该作者
本帖最后由 三月廿七 于 2012-06-01 18:05 编辑
walleeee 发表于 2012-06-01 17:58
回复 8# 三月廿七


还有MAX_PATH,根本就不行嘛,什么256个字符,坑爹么?ntfs一个文件名就1-256字符,难道路径都不见了?没层次了?
//

好像 文件名256个字符,是不允许存到文件夹里的
WIN32 还有哪个函数不畸形的吗?

函数版本多的让我抓狂
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP