简体   繁体   English

C ++将所有文件从一个目录移动到另一个目录

[英]C++ move all files from one directory to another

I have a problem moving data from one directory to another.我在将数据从一个目录移动到另一个目录时遇到问题。 I want to do as below (bash) but in C++:我想做如下(bash),但在 C++ 中:

mv /testdir/* /testdest/

So it should basically move all files located in /testdir to /testdest .所以它应该基本上将位于/testdir的所有文件移动到/testdest I've already tried rename in C++ but it does not actually move data, it just renames directories.我已经尝试在 C++ 中rename ,但它实际上并没有移动数据,它只是重命名目录。

My current code:我当前的代码:

#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])
}

I am executing this as below:我正在执行如下:

./static-mv /testdir/ /testdest/

Effect of this is rename /testdir/ to /testdest/ (with its content).这样做的效果是将/testdir/重命名为/testdest/ (及其内容)。 After this, /testdir/ is no longer available which is not the expected result.在此之后, /testdir/不再可用,这不是预期的结果。

// 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...

You might use nftw(3) to collect all the paths, and then loop on mkdir(2) & rename(2) .您可以使用nftw(3)收集所有路径,然后在mkdir(2)rename(2)上循环。 nftw uses opendir(3) , readdir(3) , closedir , stat(2) (which you might directly use). nftw使用opendir(3)readdir(3)closedirstat(2) (您可以直接使用)。

With a recent C++17 implementation you might use <filesystem>对于最近的 C++17 实现,您可能会使用<filesystem>

If some other process is writing into subdirectories, you could be in trouble (as mv probably is).如果其他进程正在写入子目录,您可能会遇到麻烦(可能是mv )。

Perhaps running /bin/mv (that file path is standardized by POSIX) in another process could be simpler.也许在另一个进程中运行/bin/mv (该文件路径由 POSIX 标准化)可能更简单。

There could be issues if /testdir and /testdest are in different file systems (and mount points), since rename(2) works only in one file system.如果/testdir/testdest位于不同的文件系统(和挂载点)中,则可能会出现问题,因为rename(2)仅适用于一个文件系统。 mv knows how to handle that (in that case, it copy files before deleting the source). mv知道如何处理(在这种情况下,它会在删除源之前复制文件)。 Also, some of the sub-directories of /testdir could be mount points, etc..此外, /testdir的一些子目录可能是挂载点等。

If both /testdir/ and /testdest/ are in the same file system and there is no mount points under /testdir , you could just loop with opendir , readdir , closedir , skip the .如果/testdir//testdest/都在同一个文件系统中,并且/testdir下没有挂载点,则可以循环使用opendirreaddirclosedir ,跳过. and .. entries, construct for each directory entry the corresponding full source and destination paths, and use rename on these...条目,为每个目录条目构造相应的完整源路径和目标路径,并在这些路径上使用rename

Of course, mv is free software, in GNU coreutils , and you might study its source code (it is less simple that what you might believe, since it handles corner cases).当然, mv是自由软件,在GNU coreutils中,你可以研究它的源代码(它不像你想象的那么简单,因为它处理了极端情况)。 You could also use strace(1) to understand which system calls (listed in syscalls(2) ) are involved by some mv command or process.您还可以使用strace(1)来了解某些mv命令或进程涉及哪些系统调用(在syscalls(2)中列出)。

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);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM