Created
February 21, 2022 19:07
-
-
Save doomed-phobos/5cdcbc7b8e287a9ef96197372efd9589 to your computer and use it in GitHub Desktop.
Search recursive following a pattern extension.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ================ | |
* Glob and Copy | |
* ================ | |
* «» Add this in manifest file for disable maximum path length limitation: | |
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | |
<assembly xmlns="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0"> | |
<application> | |
<windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings"> | |
<ws2:longPathAware>true</ws2:longPathAware> | |
</windowsSettings> | |
</application> | |
</assembly> | |
*/ | |
#include <iostream> | |
#include <string_view> | |
#include <windows.h> | |
#include <vector> | |
#include <functional> | |
#include <Shlwapi.h> | |
size_t nFilesCopied = 0; | |
std::wstring get_real_path(const std::wstring_view& path); | |
void copy_file(const std::wstring& src_dir, const std::wstring& dst_dir, const std::wstring& filename); | |
template<typename Fn, | |
typename = typename std::enable_if_t<std::is_convertible_v< | |
Fn, std::function<void(const std::wstring& /*src_dir*/, const std::wstring& /*filename*/)>>>> | |
void search_recursive(const std::wstring& dir, const std::wstring& pattern, Fn&& fn) { | |
HANDLE hSearch; | |
WIN32_FIND_DATAW ffd; | |
SetCurrentDirectoryW(dir.c_str()); | |
hSearch = FindFirstFileW(L"*", &ffd); | |
if(hSearch != INVALID_HANDLE_VALUE) { | |
do { | |
if(ffd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) { | |
continue; | |
} else if(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { | |
if(wcscmp(ffd.cFileName, L".") != 0 && | |
wcscmp(ffd.cFileName, L"..") != 0) | |
search_recursive(dir + L'\\' + ffd.cFileName, pattern, fn); | |
} else { | |
if(PathMatchSpecW(ffd.cFileName, pattern.c_str()) == TRUE) | |
fn(dir, ffd.cFileName); | |
} | |
} while(FindNextFileW(hSearch, &ffd) != 0); | |
} | |
FindClose(hSearch); | |
} | |
int wmain(int argc, wchar_t* argv[]) { | |
if(argc != 4) { | |
wprintf(L"[!] Usage: GlobAndCopy <pattern> <src_dir> <dst_dir>\n"); | |
return -1; | |
} | |
const std::wstring_view pattern = argv[1]; | |
const std::wstring_view src_dir = argv[2]; | |
const std::wstring_view dst_dir = argv[3]; | |
if(src_dir.size() > MAX_PATH - pattern.size() || | |
dst_dir.size() > MAX_PATH - pattern.size()) { | |
wprintf(L"[!] <src_dir> or <dst_dir> is too large\n", src_dir, dst_dir); | |
return -1; | |
} | |
wprintf(L"[*] Finding %s in %s\n", pattern.data(), src_dir.data()); | |
auto real_src_dir = get_real_path(src_dir); | |
auto real_dst_dir = get_real_path(dst_dir); | |
wprintf(L"[*] Source Dir: %s\n" | |
L"[*] Destination Dir: %s\n", real_src_dir.c_str(), real_dst_dir.c_str()); | |
search_recursive( | |
real_src_dir, | |
std::wstring(pattern), | |
[&](const std::wstring& src_dir, const std::wstring& filename) {copy_file(src_dir, real_dst_dir, filename);}); | |
wprintf(L"[*] %lld files copied!", nFilesCopied); | |
return 0; | |
} | |
// Convert . or .. to real path. | |
// If exists \, delete it | |
std::wstring get_real_path(const std::wstring_view& path) { | |
wchar_t real_path[MAX_PATH]; | |
GetFullPathNameW(path.data(), MAX_PATH, real_path, NULL); | |
size_t size = wcslen(real_path); | |
if(size > MAX_PATH) | |
return std::wstring(); | |
if(real_path[size-1] == L'\\') | |
real_path[size-1] = 0; | |
return real_path; | |
} | |
void copy_file(const std::wstring& src_dir, const std::wstring& dst_dir, const std::wstring& filename) { | |
std::wstring src_file = src_dir + L'\\' + filename; | |
SetCurrentDirectoryW(dst_dir.c_str()); | |
if(CopyFileW( | |
src_file.c_str(), | |
filename.c_str(), | |
TRUE) == FALSE) { | |
wprintf(L"[!] File %s generates error code %ld\n", src_file.c_str(), GetLastError()); | |
return; | |
} | |
wprintf(L"[*] Copied %s\n", src_file.c_str()); | |
++nFilesCopied; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment