Advertisement
mrAnderson33

аналог ls для произвольного количества файлов(для UNIX)

Jun 1st, 2017
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.19 KB | None | 0 0
  1. /*
  2. рекурсия в функции calc_size_file не позволяет выводить содержимое директорий переданных по полному пути и содержимое корня /
  3. */
  4.  
  5. #include <unistd.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <dirent.h>
  9. #include <string.h>
  10. #include <sys/stat.h>
  11.  
  12. // посчитать размер afqkf
  13. long long calc_size_file( char* dir );
  14. // вывевсти на экран тип, размер, имя файлов из указанной директории
  15. void print_dir( char* dir );
  16. // определить тип файла
  17. char display_file_type ( int st_mode );
  18.  
  19.  
  20. int main( int argc, char* argv[] ) {
  21.  
  22.     if ( argc < 2 ) { // если неверно задан аргумент
  23.         // выводим сообщение об ошибке
  24.         fprintf( stderr, "Invalid argument! Use: viewdir <directory>\n" );
  25.         return EXIT_FAILURE; // выходим из программы
  26.     }
  27.     // выводим сообщение о том какую директорию сканируем
  28.     for(int i = 1; i <argc; ++i)
  29.     {
  30.         printf( "Directory scan of  %s: \n", argv[ i ] );
  31.         print_dir( argv[ i ] ); // выводим на экран тип, размер, имя файлов указанной директории
  32.     }
  33.     return EXIT_SUCCESS;
  34. }
  35.  
  36. void print_dir( char* dir ){
  37.     DIR *dp; // поток каталога
  38.     struct dirent *entry; // для имени и индекса файла
  39.     struct stat statbuf; // для информации о файле
  40.  
  41.     if ( ( dp = opendir( dir ) ) == NULL ) { // если не смогли открыть поток каталога
  42.         fprintf( stderr, "cannot open directory: %s\n", dir ); // выводим сообщение об ошибке
  43.         return; // выходим из функции
  44.     }
  45.  
  46.     chdir( dir ); // перемещаемся в указанную директорию
  47.  
  48.     while ( ( entry = readdir( dp ) ) != NULL ) { // цикл по всем файлам указанной директории
  49.         lstat( entry->d_name, &statbuf ); // считываем информацию о файле в структуру
  50.  
  51.         if ( S_ISDIR( statbuf.st_mode ) ) { // если это директория
  52.  
  53.             // проверяем является ли она . или ..
  54.             if ( strcmp( ".", entry->d_name ) == 0 ||
  55.                     strcmp( "..", entry->d_name ) == 0 ) // и если да,
  56.                 continue; // то игнорируем ее, возвращаясь в начало цикла
  57.  
  58.             // считаем размер директории
  59.             long long size = calc_size_file( entry->d_name );
  60.  
  61.             // если размер посчитать не удалось, то
  62.             if ( size == -1 )
  63.                 printf ( "%c\t%s\t\t%s\n", 'd', "unknow", entry->d_name ); // выводим на экран информацию об этом
  64.             else // а если все в порядке
  65.                 // выводим информацию о директории
  66.                 printf( "%c\t%lld\t\t/%s\n", 'd', ( long long )statbuf.st_size + size, entry->d_name );
  67.         }
  68.         else{ // иначе - если это НЕ директория, то выводим информацию о файле
  69.             printf( "%c\t%lld\t\t/%s\n", display_file_type( statbuf.st_mode ), ( long long )statbuf.st_size, entry->d_name );
  70.         }
  71.     }
  72.  
  73.     closedir( dp ); // закрываем указаннню директорию
  74. }
  75.  
  76. long long calc_size_file( char* dir ) {
  77.  
  78.     static int err_code = 0; // для запоминания ошибки
  79.     long long  sum_size = 0; // для размера файла
  80.  
  81.     DIR *dp; // поток каталога
  82.     struct dirent *entry; // для имени и индекса файла
  83.     struct stat statbuf; // для информации о файле
  84.  
  85.     if ( ( dp = opendir( dir ) ) == NULL ) {  // если не смогли открыть поток каталога
  86.         err_code = 1; // запоминаем это
  87.         return -1;
  88.     }
  89.  
  90.     // а если все нормально, то
  91.     chdir( dir );  // перемещаемся в указанную директорию
  92.     // цикл по всем файлам указанной директории
  93.     while ( ( entry = readdir( dp ) ) != NULL && !err_code) {
  94.         lstat( entry->d_name, &statbuf ); // считываем информацию о файле в структуру
  95.  
  96.         if ( S_ISDIR( statbuf.st_mode ) ) { // если это директория
  97.  
  98.             // проверяем является ли она . или ..
  99.             if ( strcmp( ".", entry->d_name ) == 0 ||
  100.                     strcmp( "..", entry->d_name ) == 0 ) // и если да,
  101.                 continue; // то игнорируем ее, возвращаясь в начало цикла
  102.  
  103.             // прибавляем к общему размеру размер текущей директории
  104.             // ( 4096 -  обычно такой размер имеют директории, но если в директории МНОГО данных, то размер может быть и больше )
  105.             // далее считаем размер всех файлов, содержащихся в текущей директории и прибавляем к общему размеру
  106.             // а чтобы посчитать - РЕКУРСИВНО вызововем нашу функцию и т.о. спустимся на уровень ниже
  107.             sum_size += ( long long )statbuf.st_size + calc_size_file( entry->d_name ); // РЕКУРСИЯ
  108.  
  109.             if ( err_code ) // если была ошибка,
  110.                 return -1; // то завершаем функцию с ошибочным кодом возврат
  111.  
  112.         }
  113.         else{
  114.             // иначе - если это НЕ директория, то прибавляем к общему размеру текущей директории размер данного файла
  115.             sum_size += ( long long )statbuf.st_size;
  116.         }
  117.     }
  118.  
  119.  
  120.     // после того как закончили считать размер очередной директории - перемещаемся на уровень выше
  121.     // т.е. в предыдущию директорию
  122.     chdir( ".." );
  123.     closedir( dp ); // закрываем поток каталога
  124.  
  125.     return sum_size; // а если все нормально, то возвращаем искомый размер
  126. }
  127.  
  128. char display_file_type ( int st_mode ) {
  129.     // тут все ясно
  130.     switch ( st_mode & S_IFMT ) {
  131.         case S_IFDIR:
  132.             return 'd';
  133.         case S_IFCHR:
  134.             return 'c';
  135.         case S_IFBLK:
  136.             return 'b';
  137.         case S_IFREG:
  138.             return 'r';
  139.         case S_IFLNK:
  140.             return 'l';
  141.         case S_IFSOCK:
  142.             return 's';
  143.         case S_IFIFO:
  144.             return 'f';
  145.         default:
  146.             return 'u';
  147.     }
  148. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement