C ++ переместить все файлы из одного каталога в другой - PullRequest
0 голосов
/ 14 мая 2018

У меня проблема с переносом данных из одного каталога в другой.Я хочу сделать, как показано ниже (bash), но в C ++:

mv /testdir/* /testdest/

Таким образом, он должен в основном переместить все файлы, расположенные в /testdir в /testdest.Я уже пробовал rename в C ++, но на самом деле он не перемещает данные, он просто переименовывает каталоги.

Мой текущий код:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <iostream>
#include <unistd.h>
#include <dirent.h>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <string>
#include <sys/stat.h>
#include <syslog.h>
#include <fstream>

using namespace std;

int main( int argc, char *argv[] )
{
  rename (argv[1], argv[2])
}

Я выполняю это, как показано ниже:

./static-mv /testdir/ /testdest/

В результате переименовывается /testdir/ в /testdest/ (с его содержимым).После этого /testdir/ больше не доступен, что не является ожидаемым результатом.

Ответы [ 3 ]

0 голосов
/ 15 мая 2018
// static-mv.cpp
#include<experimental/filesystem>
#include<cassert>
#include<iostream>

int main(int argc, char* argv[]){
    assert(argc >= 3);
    namespace fs = std::experimental::filesystem;
    for(fs::path p : fs::directory_iterator(argv[1])){
        std::cout << p << " -> " << argv[2]/p.filename() << std::endl;
        fs::rename(p, argv[2]/p.filename());
    }
}

$ c++ -std=c++11 static-mv.cpp -o static-mv -lstdc++fs

$ mkdir dir1; cd dir1; touch file.a; touch file.b; cd ..; ls dir1/

file.a  file.b

$ mkdir dir2;

$ ./static-mv dir1 dir2

"dir1/file.a" -> "dir2/file.a"
"dir1/file.b" -> "dir2/file.b"

$ ls dir2/

file.a  file.b

$ success!

bash: success!: command not found...
0 голосов
/ 27 мая 2019
void move(char const *sorc, char const *dst, bool createRoot = true) {
    namespace fs = std::experimental::filesystem;

    if (createRoot)
        fs::create_directory(dst);

    for(fs::path p: fs::directory_iterator(sorc)){
        fs::path destFile = dst/p.filename();

        if (fs::is_directory(p)) {
            fs::create_directory(destFile);
            move(p.string().c_str(), destFile.string().c_str(), false);
        } else {
            //std::cout << "updated " << p.string().c_str() << std::endl;
            fs::rename(p, destFile);
        }
    }
}
0 голосов
/ 14 мая 2018

Вы можете использовать nftw (3) , чтобы собрать все пути, а затем зацикливаться на mkdir (2) & rename (2) . nftw использует opendir (3) , readdir (3) , closedir, stat (2) (который вы можете использовать напрямую).

В недавней реализации C ++ 17 вы можете использовать <filesystem>

Если какой-то другой процесс записывает в подкаталоги, у вас могут быть проблемы (как, вероятно, mv).

Возможно, выполнение /bin/mv (этот путь к файлу стандартизирован POSIX) в другом процессе может быть проще.

Могут возникнуть проблемы, если /testdir и /testdest находятся в различных файловых системах (и точках монтирования), поскольку rename (2) работает только в одной файловой системе. mv знает, как с этим справиться (в этом случае он копирует файлы перед удалением источника). Кроме того, некоторые из подкаталогов /testdir могут быть точками монтирования и т. Д.

Если /testdir/ и /testdest/ находятся в одной и той же файловой системе и нет точек монтирования под /testdir, вы можете просто выполнить цикл с opendir, readdir, closedir, пропустить . и .. записей, создайте для каждой записи каталога соответствующие полные пути источника и назначения и используйте rename для них.

Конечно, mv является свободным программным обеспечением, в GNU coreutils, и вы можете изучить его исходный код (он не так прост, как вы могли бы подумать, поскольку он обрабатывает угловые случаи). Вы также можете использовать strace (1) , чтобы понять, какие системные вызовы (перечислены в syscalls (2) ) задействованы какой-то командой или процессом mv.

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