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
);
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;
}
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
);
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")
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
);
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
);
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;
}
I hope you have learnt something new today. Follow the links to reach me
- Email: tbhaxor@gmail.com
- Twitter: @tbhaxor
- Facebook: @tbhaxor
- GitHub: @tbhaxor
- LinkedIn: @gurkirat--singh
- Instagram: @_tbhaxor_
Top comments (0)