DEV Community

loading...

Windows System Programming: Move / Delete a File or Folder

Gurkirat Singh
Yet another noob script kiddie and non TPP registered failure :)
・4 min read

Hello devs

In this post I will cover moving a file or directory from one path (source) to another (destination). Along with this moving part, I will also cover how you can delete an existing file or folder.

So basically if you want to rename a file / directory or even change the location of a file / directory, you need to work move "it" from source path to the destination path.

To perform move operation, you need to call MoveFileA function from WinBase.h.

If you would see, MoveFile is a pretty straightforward function

BOOL MoveFile(
  LPCTSTR lpExistingFileName,
  LPCTSTR lpNewFileName
);
Enter fullscreen mode Exit fullscreen mode

Function parameters description as follows

  • lpExistingFileName → Location of the file/folder in the local computer you want to move. If the path is not found, it might return ERROR_FILE_NOT_FOUND.
  • lpNewFileName → The new name for the non existing **file or directory. If you will pass the path that already exists, it will return **ERROR_ALREADY_EXISTS.

In case you are wondering how to overwrite the existing path, use MoveFileExA, where the 3rd parameter should be MOVEFILE_REPLACE_EXISTING.

Note: In MoveFileExA, If lpNewFileName or lpExistingFileName name a directory and lpExistingFileName exists, an error is reported.

The complete code as follows

#include <Windows.h>
#include <iostream>
#include <WinBase.h>

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

    if (argc < 3) {
        printf("usage: %s <old filename / dirname> <new filename / dirname>\n", argv[0]);
        return 1;
    }

    /** 
      * Function Documentation
      * https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-movefilea
      */
    BOOL flag = MoveFileA(argv[1], argv[2]);

    if (flag) {
        printf("Renamed\n");
    }
    else {
        switch (GetLastError())
        {
        case ERROR_FILE_NOT_FOUND:
            printf("ERR: File '%s' not found\n", argv[1]);
            break;
        case ERROR_ALREADY_EXISTS:
            printf("ERR: '%s' already exists\n", argv[2]);
            break;
        default:
            printf("ERR: %d\n", GetLastError());
            break;
        }
        return 1;
    }
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Now comes the part of removing file and directory.

Unlike moving operation, the remove operation is different for file and directory. So in this I will introduce another approach to detect to check if the path exists and determining if the existing path is a file or directory.

First of all, you need to check the existence of the path that has to be removed. For this, you need to use PathFileExistsA, declared in shlwapi.h.

BOOL PathFileExistsA(
  LPCSTR pszPath
);
Enter fullscreen mode Exit fullscreen mode

Function parameters description as follows

  • pszPath → A pointer to null-terminated const char* that contains the full path of the object to verify.

If the path exists, it will return TRUE, otherwise FALSE.

To make this code in working condition, you should tell the linker to link the Shlwapi.lib library as well.

NOTE: Header file is a something that contains only the declaration/prototype of the functions. But the actual definition (steps describing the function execution, aka function body) are written in library. [READ MORE]

So in C++, the libraries are linked with pragma directive, comment(lib, "<library name or path>")

The snippet to link Shlwapi.lib would be

#pragma comment(lib, "Shlwapi.lib")
Enter fullscreen mode Exit fullscreen mode

Ok, so now come back to removing thing. Once it's verified that file exists, it's time to determine type of path (whether it's a file or a directory). For this, you need to call GetFileAttributesA from fileapi.h.

DWORD GetFileAttributesA(
  LPCSTR lpFileName
);
Enter fullscreen mode Exit fullscreen mode

Function parameters description as follows

  • lpFileName → The name of the file or directory you want to look file attributes for.

It will return a numerical output, which is mapped to file attribute constants. In this case, I am interested in FILE_ATTRIBUTE_DIRECTORY, the handle that identifies a directory.

At this time, you know if the path exists or not and whether it's a directory or a file. Now you should perform the remove operation on it.

To delete file use DeleteFileA and for directory use RemoveDirectoryA

Both of them are declared in fileapi.h and require only one parameter (type = const char*). But in case of RemoveDirectoryA, path must specify an empty directory.

BOOL RemoveDirectoryA(
  LPCSTR lpPathName
);

BOOL DeleteFileA(
  LPCSTR lpFileName
);
Enter fullscreen mode Exit fullscreen mode

The complete code as follows

#include <Windows.h>
#include <fileapi.h>
#include <iostream>
#include <Shlwapi.h>

#pragma comment(lib, "Shlwapi.lib")

int main(int argc, char* argv[]) {
    if (argc == 1) {
        printf("usage: %s <file or directory name>\n", argv[0]);
        return 1;
    }

    // checking if file exists (for getting file attributes)
    // https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathfileexistsa
    if (PathFileExistsA(argv[1])) {
        // https://docs.microsoft.com/en-gb/windows/win32/api/fileapi/nf-fileapi-getfileattributesa
        if (GetFileAttributesA(argv[1]) == FILE_ATTRIBUTE_DIRECTORY) {
            // the path is a diretory
            // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectorya
            if (RemoveDirectoryA(argv[1])) {
                printf("Directory '%s' deleted\n", argv[1]);
            } else {
                switch (GetLastError())
                {
                default:
                    printf("ERROR: DeleteFileA - %d\n", GetLastError());
                    break;
                }
            }
        } else {
            // the path is a file
            // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-deletefilea
            if (DeleteFileA(argv[1])) {
                printf("File '%s' deleted\n", argv[1]);
            } else {
                switch (GetLastError())
                {
                default:
                    printf("ERROR: DeleteFileA - %d\n", GetLastError());
                    break;
                }
            }
        }
    } else {
        printf("File / Directory '%s' not exists\n", argv[1]);
        return 1;
    }
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

I hope you have learnt something new today. Follow the links to reach me

Discussion (0)