Сортировка файлов по типу файла - PullRequest
0 голосов
/ 02 апреля 2020

Программа ниже используется для классификации файлов на основе их типов файлов, точнее их расширения. Например, команда ./sorting -f file1.jpg file2.txt file3.c создаст папки jpg, txt и c и поместит файлы внутрь.

Вот код

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>

void *check(char *argv[]);
void *mkdir(char *argv[]);
void *mvdr(char *argv[]);
pid_t child;

int main(int argc, char *argv[]) {
    pthread_t files[argc];  // inisialisasi awal
    int iret[argc];

    // 1. how many threads you need, setiap file
    //      -- setiap file setiap argc & argv

    // create thread every files
    if (argc == 1)
        return 0;

    if (strcmp(argv[1], "-f") == 0) {
        for (int i = 2; i < argc; ++i) {
            iret[i] = pthread_create( &files[i], NULL, check, argv[i]); // membuat thread pertama
        }
    }
    return 0;
}

void *check(char *argv[]) {
    pthread_t move, make;
    int types = 0;
    int imv, imk;
    char type[80] = {0};
    char *tok = NULL;

    tok = strtok(argv, ".");
    while (tok) {
        strcpy(type, tok);
        tok = strtok(NULL, ".");

        imv = pthread_create(&make, NULL, mkdir, argv);

        imk = pthread_create(&move, NULL, mvdr, argv);

        pthread_join(mkdir, NULL);
        pthread_join(mvdr, NULL);
    }
}

void *mkdir(char *argv[]) {
    child = fork();

    if (child == 0) {
        char *mkdr[3] = { "mkdir", argv, NULL };
        execv("/usr/bin/mkdir", mkdr);
    }
}

void *mvdr(char *argv[]) {
    child = fork();

    if (child == 0) {
        char *mv[5] = { "mv", "-v", argv, argv, NULL };
        execv("/usr/bin/mv", mv);
    }
}

Я использую execv для создания и перемещения файлов. Это должно быть связано с резьбой, трубами или розетками. У вас есть какие-либо подсказки, как это решить? Ваша помощь очень ценится

1 Ответ

1 голос
/ 03 апреля 2020

Не ясно, какие ограничения накладываются на упражнения в классе, и мой индонезийский язык не так хорош, как Энгли sh ОП, и Chrome, похоже, не хотел переводить файл README.md на Страница GitHub https://github.com/VYPRATAMA009/sisop-modul-3.

Для решения проблемы, описанной в вопросе (с точки зрения желаемого результата), нет необходимости использовать ни потоки, ни fork() и exec*() для реализации программы.

Практически всегда плохая идея смешивать потоки с fork() и exec*() - выбрать многопоточность или многопроцессорность, но не оба одновременно.

Программа должна обработать параметр (-f, чтобы проверить только обычные файлы; не перемещать файлы любого типа), а затем обработать любые остаточные имена файлов. Обработка имени состоит из проверки обычного файла, если необходимо, поиска расширения с помощью strrchr(), создания каталога с таким именем расширения, затем форматирования имени в подкаталоге, а затем переименования файла, чтобы он перешел в каталог. и освобождая выделенную память.

#include "stderr.h"
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

static bool is_regular(const char *filename);
static void mk_directory(const char *dirname);
static void move_file(const char *filename);

static bool check_file = false;

static const char usestr[] = "[-f] file [...]";
static const char optstr[] = "f";

int main(int argc, char *argv[])
{
    int opt;
    err_setarg0(argv[0]);

    while ((opt = getopt(argc, argv, optstr)) != -1)
    {
        switch (opt)
        {
        case 'f':
            check_file = true;
            break;
        default:
            err_usage(usestr);
            /*NOTREACHED*/
        }
    }

    if (optind == argc)
        err_usage(usestr);

    for (int i = optind; i < argc; i++)
        move_file(argv[i]);

    return 0;
}

static bool is_regular(const char *filename)
{
    struct stat sb;
    if (stat(filename, &sb) != 0)
        err_syserr("failed to get status of file '%s': ", filename);
    return S_ISREG(sb.st_mode);
}

static void mk_directory(const char *dirname)
{
    if (mkdir(dirname, 0755) != 0)
    {
        if (errno != EEXIST)
            err_syserr("failed to create directory '%s': ", dirname);
    }
}

static void move_file(const char *filename)
{
    char *dot = strrchr(filename, '.');
    if (check_file && !is_regular(filename))
    {
        err_remark("'%s' is not a regular file\n", filename);
        return;
    }
    if (dot == NULL || dot == filename || dot[1] == '\0')
    {
        err_remark("file '%s' does not have an extension\n", filename);
        return;
    }
    mk_directory(dot + 1);
    size_t namelen = strlen(dot + 1) + strlen(filename) + sizeof("/");
    char *buffer = malloc(namelen);
    if (buffer == NULL)
        err_syserr("failed to allocated %zu bytes memory: ", namelen);
    sprintf(buffer, "%s/%s", dot + 1, filename);
    if (rename(filename, buffer) != 0)
        err_syserr("failed to rename '%s' to '%s': ", filename, buffer);
    free(buffer);
}

Это использует мои функции отчетов об ошибках, которые доступны в моем репозитории SOQ (вопросы о переполнении стека) на GitHub в виде файлов stderr.c и stderr.h в подкаталоге src / libsoq .

Имеется каталог, который начинается с:

$ ls -la
total 56
drwxr-xr-x   15 jonathanleffler  staff   480 Apr  2 22:14 .
drwxr-xr-x  241 jonathanleffler  staff  7712 Apr  2 22:16 ..
-rw-r--r--    1 jonathanleffler  staff     0 Apr  2 22:12 .junk
-rw-r--r--    1 jonathanleffler  staff     0 Apr  2 22:12 .junk.
-rw-r--r--    1 jonathanleffler  staff  1036 Apr  2 22:06 binge.c
-rw-r--r--    1 jonathanleffler  staff   666 Apr  2 22:06 garbage.c
-rw-r--r--    1 jonathanleffler  staff  1772 Apr  2 21:11 junk-0.0.1.tar.gz
-rw-r--r--    1 jonathanleffler  staff  1772 Apr  2 21:10 junk-1.txt
-rw-r--r--    1 jonathanleffler  staff  1772 Apr  2 21:10 junk-2.txt
-rw-r--r--    1 jonathanleffler  staff     0 Apr  2 22:12 junk.
-rw-r--r--    1 jonathanleffler  staff  1772 Apr  2 21:10 junk.c
drwxr-xr-x    3 jonathanleffler  staff    96 Apr  2 22:04 junk.dir
prw-r--r--    1 jonathanleffler  staff     0 Apr  2 22:10 junk.fifo
lrwxr-xr-x    1 jonathanleffler  staff     8 Apr  2 21:12 junk.lnk -> junk.dir
-rw-r--r--    1 jonathanleffler  staff   812 Apr  2 22:06 trash.c
$

с запущенной программой (mf29 скомпилировано из * 1032) *) дает:

$ mf29 -f .j* *
mf29 -f .j* *
mf29: file '.junk' does not have an extension
mf29: file '.junk.' does not have an extension
mf29: file 'junk.' does not have an extension
mf29: 'junk.dir' is not a regular file
mf29: 'junk.fifo' is not a regular file
mf29: 'junk.lnk' is not a regular file
$ ls -la
total 0
drwxr-xr-x   11 jonathanleffler  staff   352 Apr  2 22:37 .
drwxr-xr-x  241 jonathanleffler  staff  7712 Apr  2 22:16 ..
-rw-r--r--    1 jonathanleffler  staff     0 Apr  2 22:12 .junk
-rw-r--r--    1 jonathanleffler  staff     0 Apr  2 22:12 .junk.
drwxr-xr-x    6 jonathanleffler  staff   192 Apr  2 22:37 c
drwxr-xr-x    3 jonathanleffler  staff    96 Apr  2 22:37 gz
-rw-r--r--    1 jonathanleffler  staff     0 Apr  2 22:12 junk.
drwxr-xr-x    3 jonathanleffler  staff    96 Apr  2 22:04 junk.dir
prw-r--r--    1 jonathanleffler  staff     0 Apr  2 22:10 junk.fifo
lrwxr-xr-x    1 jonathanleffler  staff     8 Apr  2 21:12 junk.lnk -> junk.dir
drwxr-xr-x    4 jonathanleffler  staff   128 Apr  2 22:37 txt
$

Затем восстановление перемещенных файлов и повторный запуск без опции -f приводит к:

$ mv ?/* ??/* ???/* ????/* .
$ rmdir ? ?? ??? ????
$ mf29 .j* *
mf29: file '.junk' does not have an extension
mf29: file '.junk.' does not have an extension
mf29: file 'junk.' does not have an extension
$ ls -la
total 0
drwxr-xr-x   11 jonathanleffler  staff   352 Apr  2 22:42 .
drwxr-xr-x  241 jonathanleffler  staff  7712 Apr  2 22:16 ..
-rw-r--r--    1 jonathanleffler  staff     0 Apr  2 22:12 .junk
-rw-r--r--    1 jonathanleffler  staff     0 Apr  2 22:12 .junk.
drwxr-xr-x    6 jonathanleffler  staff   192 Apr  2 22:42 c
drwxr-xr-x    3 jonathanleffler  staff    96 Apr  2 22:42 dir
drwxr-xr-x    3 jonathanleffler  staff    96 Apr  2 22:42 fifo
drwxr-xr-x    3 jonathanleffler  staff    96 Apr  2 22:42 gz
-rw-r--r--    1 jonathanleffler  staff     0 Apr  2 22:12 junk.
drwxr-xr-x    3 jonathanleffler  staff    96 Apr  2 22:42 lnk
drwxr-xr-x    4 jonathanleffler  staff   128 Apr  2 22:42 txt
$

Если вы предоставляете имена с несколькими компонентами пути, это обычно ошибка:

$ ../mf29 ~/src/cmd/timecmd.c
mf29: failed to rename '/Users/jonathanleffler/src/cmd/timecmd.c' to 'c//Users/jonathanleffler/src/cmd/timecmd.c': error (2) No such file or directory
$

Существуют различные способы, которые можно исправить - это зависит от желаемого результата. Функция POSIX basename() может быть полезной. Функция mkpath() также может быть полезна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...