How to search and move files from one path to another C++? - c++

I'm trying to search all files that follow this pattern "console-*" and move them to another path on my machine if they exist. (For example from: /documents/fs/pstore to /sdk/sys/kernel_dump/).
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int dirExists(const char *pathname)
{
struct stat info;
if( stat( pathname, &info ) != 0 )
return 0; // printf( "cannot access %s\n", pathname );
else if( info.st_mode & S_IFDIR ) // S_ISDIR() doesn't exist on my windows
return 1; // printf( "%s is a directory\n", pathname );
else
return 0; // printf( "%s is no directory\n", pathname );
}
int main()
{
const char *path = "/documents/fs/pstore";
if(dirExists(path))
system("mv /documents/fs/pstore/console-* /sdk/sys/kernel_dump/ ");
else
printf( "error" );
return 0;
}
I've experienced with the code above, but it does not seem to work properly, should I try another approach, maybe with the rename() function? (I'm working on Linux)
Any advice would be greatly appreciated, thank you in advance.

You can call glob() and rename() C functions in Linux if C++17's std::filesystem is not an option for you. glob() gives you the list of files that matches globbing pattern like *, ? and []. However, rename() may fail if the mount position of from and to path are not identical. In this case, you should create your own copy and remove file function.

Related

C++ how to find file path of the file I am working on in my program [duplicate]

I want to create a file in the current directory (where the executable is running).
My code:
LPTSTR NPath = NULL;
DWORD a = GetCurrentDirectory(MAX_PATH,NPath);
HANDLE hNewFile = CreateFile(NPath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
I get exception at GetCurrentDirectory().
Why am I getting an exception?
I would recommend reading a book on C++ before you go any further, as it would be helpful to get a firmer footing. Accelerated C++ by Koenig and Moo is excellent.
To get the executable path use GetModuleFileName:
TCHAR buffer[MAX_PATH] = { 0 };
GetModuleFileName( NULL, buffer, MAX_PATH );
Here's a C++ function that gets the directory without the file name:
#include <windows.h>
#include <string>
#include <iostream>
std::wstring ExePath() {
TCHAR buffer[MAX_PATH] = { 0 };
GetModuleFileName( NULL, buffer, MAX_PATH );
std::wstring::size_type pos = std::wstring(buffer).find_last_of(L"\\/");
return std::wstring(buffer).substr(0, pos);
}
int main() {
std::cout << "my directory is " << ExePath() << "\n";
}
The question is not clear whether the current working directory is wanted or the path of the directory containing the executable.
Most answers seem to answer the latter.
But for the former, and for the second part of the question of creating the file, the C++17 standard now incorporates the filesystem library which simplifies this a lot:
#include <filesystem>
#include <iostream>
std::filesystem::path cwd = std::filesystem::current_path() / "filename.txt";
std::ofstream file(cwd.string());
file.close();
This fetches the current working directory, adds the filename to the path and creates an empty file. Note that the path object takes care of os dependent path handling, so cwd.string() returns an os dependent path string. Neato.
GetCurrentDirectory does not allocate space for the result, it's up to you to do that.
TCHAR NPath[MAX_PATH];
GetCurrentDirectory(MAX_PATH, NPath);
Also, take a look at Boost.Filesystem library if you want to do this the C++ way.
An easy way to do this is:
int main(int argc, char * argv[]){
std::cout << argv[0];
std::cin.get();
}
argv[] is pretty much an array containing arguments you ran the .exe with, but the first one is always a path to the executable. If I build this the console shows:
C:\Users\Ulisse\source\repos\altcmd\Debug\currentdir.exe
IMHO here are some improvements to anon's answer.
#include <windows.h>
#include <string>
#include <iostream>
std::string GetExeFileName()
{
char buffer[MAX_PATH];
GetModuleFileName( NULL, buffer, MAX_PATH );
return std::string(buffer);
}
std::string GetExePath()
{
std::string f = GetExeFileName();
return f.substr(0, f.find_last_of( "\\/" ));
}
#include <iostream>
#include <stdio.h>
#include <dirent.h>
std::string current_working_directory()
{
char* cwd = _getcwd( 0, 0 ) ; // **** microsoft specific ****
std::string working_directory(cwd) ;
std::free(cwd) ;
return working_directory ;
}
int main(){
std::cout << "i am now in " << current_working_directory() << endl;
}
I failed to use GetModuleFileName correctly. I found this work very well.
just tested on Windows, not yet try on Linux :)
WCHAR path[MAX_PATH] = {0};
GetModuleFileName(NULL, path, MAX_PATH);
PathRemoveFileSpec(path);
Please don't forget to initialize your buffers to something before utilizing them. And just as important, give your string buffers space for the ending null
TCHAR path[MAX_PATH+1] = L"";
DWORD len = GetCurrentDirectory(MAX_PATH, path);
Reference
You should provide a valid buffer placeholder.
that is:
TCHAR s[100];
DWORD a = GetCurrentDirectory(100, s);
#include <windows.h>
using namespace std;
// The directory path returned by native GetCurrentDirectory() no end backslash
string getCurrentDirectoryOnWindows()
{
const unsigned long maxDir = 260;
char currentDir[maxDir];
GetCurrentDirectory(maxDir, currentDir);
return string(currentDir);
}
You can remove the filename from GetModuleFileName() with more elegant way:
TCHAR fullPath[MAX_PATH];
TCHAR driveLetter[3];
TCHAR directory[MAX_PATH];
TCHAR FinalPath[MAX_PATH];
GetModuleFileName(NULL, fullPath, MAX_PATH);
_splitpath(fullPath, driveLetter, directory, NULL, NULL);
sprintf(FinalPath, "%s%s",driveLetter, directory);
Hope it helps!
GetCurrentDirectory() gets the current directory which is where the exe is invoked from. To get the location of the exe, use GetModuleFileName(NULL ...). if you have the handle to the exe, or you can derive it from GetCommandLine() if you don't.
As Mr. Butterworth points out, you don't need a handle.
Why does nobody here consider using this simple code?
TCHAR szDir[MAX_PATH] = { 0 };
GetModuleFileName(NULL, szDir, MAX_PATH);
szDir[std::string(szDir).find_last_of("\\/")] = 0;
or even simpler
TCHAR szDir[MAX_PATH] = { 0 };
TCHAR* szEnd = nullptr;
GetModuleFileName(NULL, szDir, MAX_PATH);
szEnd = _tcsrchr(szDir, '\\');
*szEnd = 0;
I guess, that the easiest way to locate the current directory is to cut it from command line args.
#include <string>
#include <iostream>
int main(int argc, char* argv[])
{
std::string cur_dir(argv[0]);
int pos = cur_dir.find_last_of("/\\");
std::cout << "path: " << cur_dir.substr(0, pos) << std::endl;
std::cout << "file: " << cur_dir.substr(pos+1) << std::endl;
return 0;
}
You may know that every program gets its executable name as first command line argument. So you can use this.
Code snippets from my CAE project with unicode development environment:
/// #brief Gets current module file path.
std::string getModuleFilePath() {
TCHAR buffer[MAX_PATH];
GetModuleFileName( NULL, buffer, MAX_PATH );
CT2CA pszPath(buffer);
std::string path(pszPath);
std::string::size_type pos = path.find_last_of("\\/");
return path.substr( 0, pos);
}
Just use the templete CA2CAEX or CA2AEX which calls the internal API ::MultiByteToWideChar or ::WideCharToMultiByte。
if you don't want to use std, you can use this code:
char * ExePath()
{
static char buffer[MAX_PATH] = { 0 };
GetModuleFileName( NULL, buffer, MAX_PATH );
char * LastSlash = strrchr(buffer, '\\');
if(LastSlash == NULL)
LastSlash = strrchr(buffer, '/');
buffer[LastSlash-buffer] = 0;
return buffer;
}
I simply use getcwd() method for that purpose in Windows, and it works pretty well. The code portion is like following:
char cwd[256];
getcwd(cwd, 256);
string cwd_str = string(cwd);
The <unistd.h> library has to be added though.
To find the directory where your executable is, you can use:
TCHAR szFilePath[_MAX_PATH];
::GetModuleFileName(NULL, szFilePath, _MAX_PATH);
If you are using the Poco library, it's a one liner and it should work on all platforms I think.
Poco::Path::current()
On a give Windows C++ IDE I went crude and it was simple, reliable, but slow:
system( "cd" );
String^ exePath = Application::ExecutablePath;<br>
MessageBox::Show(exePath);
In Windows console, you can use the system command CD (Current Directory):
std::cout << "Current Directory = ";
system("cd"); // to see the current executable directory

What should I change in FindFirstFile function to make it show me full file names?

I'm a student currently learning c++ and I'm doing a course project.
I'm told to use FindFirstFile function but I can't really understand how it functions and almost blindly made it work somehow. Yet it only shows me the first letters of the files' names. What should I change to make it show me the full names so I could use it later in the program?
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <Windows.h>
#include <string.h>
int main()
{
WIN32_FIND_DATA FindFileData;
HANDLE hf;
system("chcp 1251");
hf = FindFirstFile(L"c:\\Program Files (x86)\\*", &FindFileData);
if (hf == INVALID_HANDLE_VALUE)
{
printf("Error opening files or no files found!");
return 1;
}
else
{
do
{
printf("Found file: %s", FindFileData.cFileName);
printf("\n");
} while (FindNextFile(hf, &FindFileData) != 0);
FindClose(hf);
}
system("pause");
return 0;
}
The example of what it shows: example of program's output
Like a wise man said I should've used %ls modificator in printf as I indicate long string in FindFirstFile but trying to just output regular string

Making directory with vitual studio 2012 coding in c++

Good evening everyone, please I'm writing a Library management application in c++ using virtual studio 2012. I had already writing some codes using Dev c++ it worked but when I switched to visual studio it gives error. It involves creating folders and checking if the folders were actually created. That is using dir and mkdir.
Windows and Linux (POSIX) don't support the same API for most file system functions. You can use Microsoft's platform-specific APIs like CreateDirectory() or use the POSIX-like versions like _mkdir().
If you have a more recent C++ compiler / standard library, you can use the experimental filesystem library that is slated to become part of standard C++, perhaps as early as C++17. If not, you can use Boost.Filesystem from which the pre-standard experimental library was drawn.
Here's a complete, minimal example using Boost.Filesystem, which will work on both Windows and Linux without modification:
#include <iostream>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
int main()
{
if( !fs::exists( "my_dir" ) )
{
if( fs::create_directory( "my_dir" ) )
{
std::cout << "Directory created!\n";
}
}
}
See it run: Coliru.
Here's the same code but with std::experimental::filesystem: Coliru.
You would need the appropriate include and linker paths setup in your build system for either of these to work locally. The biggest "gotcha" using the filesystem is that it throws exceptions for a lot of errors by default. You can either setup try/catch blocks at the appropriate places or pass in an error code param to make it return the status there instead.
#include <stdio.h>
#include <windows.h>
int main() {
if (!CreateDirectoryA("C:\\ABC123", NULL))
{
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
printf("Already Exists");
}else if (GetLastError()== ERROR_PATH_NOT_FOUND)
{
printf("Path not found");
}
}else{
printf("Created..");
}
}
simple function will do.
Thanks alot guys but I found this that solved my problem
#include <iostream>
#include <direct.h>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
void main( void )
{
if( _mkdir( "\\testtmp" ) == 0 )
{
printf( "Directory '\\testtmp' was successfully created\n" );
system( "dir \\testtmp" );
if( _rmdir( "\\testtmp" ) == 0 )
printf( "Directory '\\testtmp' was successfully removed\n" );
else
printf( "Problem removing directory '\\testtmp'\n" );
}
else
printf( "Problem creating directory '\\testtmp'\n" );
int a;
cin >> a;
}
the cin >> a; is just to keep the output screen so I can see the result

how we can call a system function like pwd or ls -l without using system() or exec() function using c or c++ in linux?

I am trying to print the path of the current directory using
this
execl ("/bin/pwd", "pwd", NULL);
output: /home/user/Ubuntu
and want to print a desired text before the current path.
for example:
my name /home/user/ubntu
how this will be done?
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
using namespace std;
int main(){
string command;
while(command != "exit"){
cout<< "B-17235"<<return execl ("/bin/pwd", "pwd", NULL);
cin>> command;
}
return 0;
}
Think that the majority of Unix-Linux-Gnu commands are written in C or C++. Generally there are direct API calls either system calls (man 2) or standard C library (man 3) to get the information or do the job.
To get working directory, just use getcwd() as suggested by alk.
char buffer[256];
if (NULL == getcwd(buffer, sizeof(buffer))) {
perror("can't get current dir");
return 1;
}
If you wanted to get the output of a more complex command, the most direct way would be to use popen that encloses the fork, exec, and pipe management for you :
FILE *fd = popen("/bin/pwd", "r");
char buffer[256];
if (fgets(buffer, sizeof(buffer), fd) == NULL) {
perror("can't read command");
return 1;
}
if (buffer[strlen(buffer) - 1] != '\n') {
fprintf(stderr, "path too long";
return 1;
}
pclose(fd);
// ok the working directory is is buffer
You should not use that for a command as simple as pwd.
And don't forget : man is your friend ! man getcwd and man popen will give you plenty of information ...
I am trying to print the path of the current directory
Use the library function getcwd().
To have the function available it might be necessary to #define _XOPEN_SOURCE 500 or similar (please see the man-page linked above for details on this).

How to get the directory size using c standard library

Is there is way to get the size of a directory using c standard library functions?
No. The C and C++ standard libraries do not explicitly support the concept of a directory.
As far as they are concerned, the backslashes in "C:\test\test.txt" have no special meaning. That is for the OS to handle.
What do you mean by the 'size of a directory'?
Is it the total size of the files contained into this directory?
... plus the size of the sub-directories?
Is it only linked to the number of files contained in this directory?
... plus the number of sub-directories?
... plus the size of sub-directories themselves?
None of these are possible with a single C library or system call.
Check out this post with regard to how to get the size of a file. You may need to sum up the sizes of the files in a directory to get the "directory size".
If you are using Linux these posts may be of interest to you:
How do I get the size of a directory in C?
Find directory-size through C ??? LINUX ???
This should get you going.
See here for full program:
https://stackoverflow.com/questions/3948116/how-to-integrate-two-different-processes-together-using-two-different-programs-in/3953873#3953873
For windows, see:
http://code.google.com/p/portaputty/source/browse/trunk/windows/dirent.c?r=8
or this:
http://www.softagalleria.net/dirent.php
or just use the MinGW compiler.
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h> // for opendir(), readdir(), closedir()
#include <sys/stat.h> // for stat()
dir_proc = opendir(PROC_DIRECTORY) ;
if (dir_proc == NULL)
{
perror("Couldn't open the " PROC_DIRECTORY " directory") ;
return (pid_t) -2 ;
}
// Loop while not NULL
while ( (de_DirEntity = readdir(dir_proc)) )
{
if (de_DirEntity->d_type == DT_DIR)
{
if (IsNumeric(de_DirEntity->d_name))
{
strcpy(chrarry_CommandLinePath, PROC_DIRECTORY) ;
strcat(chrarry_CommandLinePath, de_DirEntity->d_name) ;
strcat(chrarry_CommandLinePath, "/cmdline") ;
FILE* fd_CmdLineFile = fopen (chrarry_CommandLinePath, "rt") ; // open the file for reading text
if (fd_CmdLineFile)
{
fscanf(fd_CmdLineFile, "%s", chrarry_NameOfProcess) ; // read from /proc/<NR>/cmdline
fclose(fd_CmdLineFile); // close the file prior to exiting the routine
if (strrchr(chrarry_NameOfProcess, '/'))
chrptr_StringToCompare = strrchr(chrarry_NameOfProcess, '/') +1 ;
else
chrptr_StringToCompare = chrarry_NameOfProcess ;
//printf("Process name: %s\n", chrarry_NameOfProcess);
//printf("Pure Process name: %s\n", chrptr_StringToCompare );
if ( CompareFunction(chrptr_StringToCompare, cchrptr_ProcessName, intCaseSensitiveness) )
{
pid_ProcessIdentifier = (pid_t) atoi(de_DirEntity->d_name) ;
closedir(dir_proc) ;
return pid_ProcessIdentifier ;
}
}
}
}
}
closedir(dir_proc) ;