2

I am writing a C++ program to copy one file from one directory to another. I don't want to use C++ 17 features. I have already implemented this in the following code.

#include <iostream>
#include <exception>
#include <filesystem>

using std:: cout;
using std:: cin;
using std:: endl;

int main(int argc, char* argv[])
{
    if(argc != 3) {
        cout << "Usage: ./copyFile.out path_to_the_file destination_path";
        return 1;
    }
    std:: string source = argv[1];
    std:: string destination = argv[2];
    std:: filesystem:: path sourceFile = source;
    std:: filesystem:: path targetParent = destination;
    auto target = targetParent / sourceFile.filename();

    try
    {
        std:: filesystem:: create_directories(targetParent); // Recursively create the target directory path if it does not exist.
        std:: filesystem:: copy_file(sourceFile, target, std ::filesystem ::copy_options::overwrite_existing);
    }
    catch (std::exception& e) //If any filesystem error
    {
        std::cout << e.what();
    }
    return EXIT_SUCCESS;
}

I am on Linux and I want to use the OS cp command to do this. I have written this code.

#include <iostream>
#include <cstdlib>
using namespace std;

int main(int argc, char *argv[]) {

    std:: string source, destination;

    if(argc != 3) {
        cout << "Usage: ./copyFile.out path_to_the_file destination_path";
        return 1;
    }

    source = argv[1];
    destination = argv[2];

    system("cp source destination");
}

The error is: cp: source: No such file or directory, How do I do this using system()?

  • 1
    You might try `std::string cmd = "cp " + source + " " + destination;` and then `system(cmd.c_str())`;`. "source" is not the source file name ! – Damien Nov 03 '20 at 09:33
  • 2
    Why on earth would you take the gigantic step from using C++17 features all the way to using `system()` for this? – Ted Lyngmo Nov 03 '20 at 09:34

2 Answers2

1

Change this:

system("cp source destination");

To this:

std::string cmd = std::string("cp '") + source + "' '" + destination + "'";
system(cmd.c_str());

And BTW, you should either return from inside the if(argc != 3) statement, or do the rest of the code inside an else statement.

Lastly, function int main(int argc, char *argv[]) requires that you return an int value.

goodvibration
  • 5,980
  • 4
  • 28
  • 61
  • Hmmm... I'm wondering to myself whether the `("cp " + source + " " + destination).c_str()` is deallocated before being passed to the `system` function, because the actual string here is a temporary object... – goodvibration Nov 03 '20 at 09:37
  • @TedLyngmo: Because of potential spaces, right? I think I might have a bigger problem in my answer, see my comment above. – goodvibration Nov 03 '20 at 09:37
  • Anyways, took your advice (as well as my own advice)... – goodvibration Nov 03 '20 at 09:39
  • @TedLyngmo: Not sure about Linux, but in Windows I'm pretty sure that you can only use `"`, so I did that just in case it's the same on Linux. – goodvibration Nov 03 '20 at 09:48
  • I understand that I simply was passing a string "cp source destination" in the system(), could you please explain how the c_str() makes it work? – Sakshi Tanwar Nov 03 '20 at 09:48
  • @SakshiTanwar: Function `system` takes as input a `const char*`, not a `const std::string`. – goodvibration Nov 03 '20 at 09:49
  • I still have have not understood the relevance of single quotes. Please Explain? – Sakshi Tanwar Nov 03 '20 at 09:53
  • @SakshiTanwar If you have a file with whitespaces in the filename the file argument would get split into several arguments without quoting with either `"` or `'` - the single quotes being preferable to not get the shell (that is used by `system`) to resolve arguments like `$DANGER` to whatever the user has set `$DANGER` to. – Ted Lyngmo Nov 03 '20 at 09:57
  • @SakshiTanwar ... but _why_ are you using `system` for this? It's is the last function I'd use for it. – Ted Lyngmo Nov 03 '20 at 09:58
  • @TedLyngmo I actually implemented C++ 17 first but then my senior said that C++ 17 filesystem features are slower. Why should I not use system? – Sakshi Tanwar Nov 03 '20 at 10:00
  • @SakshiTanwar Your senior is wrong - `system("cp ...");` is likely to be slower. It creates a sub shell and passes arguments that needs to be interpreted by the command line interpreter until it finally calls a function that is likely to be _very_ similar to what `filesystem::copy_file` does internally. Here's one list of reasons: [Why should the system() function be avoided in C and C++?](https://stackoverflow.com/questions/19913446/why-should-the-system-function-be-avoided-in-c-and-c) Why not do some performance tests? – Ted Lyngmo Nov 03 '20 at 10:03
  • @TedLyngmo: That's a comment for the dude who asked the question I believe. – goodvibration Nov 03 '20 at 10:06
1

This can also be achieved using snprintf

char cmdbuf[BUFFER_SIZE];// use macro for defining buffer size
snprintf(cmdbuf, sizeof(cmdbuf), "cp %s %s ",argv[1],argv[2]);
system(cmdbuf);
Dharma B
  • 21
  • 9