我有一個工作代碼,它返回給定目錄下所有子目錄中的所有文件並使用通配符。例如:"C://*"
。這工作非常好。現在,我想知道是否可以使用某個文件擴展名遞歸地迭代所有文件。例如:"C://*.png"
,而不更改代碼。我正在尋找像:"C://*/../*.png"
,但我找不到解決方案。我可以使用任何通配技巧嗎?使用FindFirstFile和FindNextFile遞歸地查找具有特定擴展名的文件
0
A
回答
1
您需要遞歸搜索每個子目錄。我碰巧有一些代碼可以做到這一點,下面的代碼可能會有所幫助。
#include <functional>
#include <io.h>
enum enumflags {
ENUM_FILE = 1,
ENUM_DIR,
ENUM_BOTH
};
//return value:
// False means that the searching has been aborted by the callback function.
// It will return true otherwise.
bool enumsubfiles(
const std::wstring &dir_with_back_slant, //for example: L"C:\\", L"E:\\test\\"
const std::wstring &filename, //for example: L"123.txt", L"*.exe", L"123.???"
unsigned int maxdepth, //0 means not searching subdirectories, 1 means maximum depth of subdirectories is 1,
// pass -1 to search all the subdirectories.
enumflags flags, //search files, directories, or both.
std::function<bool(const std::wstring &dir_with_back_slant, _wfinddata_t &attrib)> callback
)
{
_wfinddata_t dat;
size_t hfile;
std::wstring fullname = dir_with_back_slant + filename;
std::wstring tmp;
bool ret = true;
hfile = _wfindfirst(fullname.c_str(), &dat);
if (hfile == -1) goto a;
do {
if (!(wcscmp(L".", dat.name) && wcscmp(L"..", dat.name))) continue;
if (((dat.attrib&_A_SUBDIR) && (!(flags&ENUM_DIR))) || ((!(dat.attrib&_A_SUBDIR)) && (!(flags&ENUM_FILE)))) continue;
ret = callback(dir_with_back_slant, dat);
if (!ret) {
_findclose(hfile);
return ret;
}
} while (_wfindnext(hfile, &dat) == 0);
_findclose(hfile);
a:
if (!maxdepth) return ret;
tmp = dir_with_back_slant + L"*";
hfile = _wfindfirst(tmp.c_str(), &dat);
if (hfile == -1) return ret;
do {
if (!(wcscmp(L".", dat.name) && wcscmp(L"..", dat.name))) continue;
if (!(dat.attrib&_A_SUBDIR)) continue;
tmp = dir_with_back_slant + dat.name + L"\\";
ret = enumsubfiles(tmp, filename, maxdepth - 1, flags, callback);
if (!ret) {
_findclose(hfile);
return ret;
}
} while (_wfindnext(hfile, &dat) == 0);
_findclose(hfile);
return ret;
}
這裏是上述函數的用法示例:
int _tmain(int argc, _TCHAR* argv[])
{
using namespace std;
//the default code page of my console window is 936
setlocale(CP_ACP, ".936");
enumsubfiles(L"C:\\", L"*.exe", 1, ENUM_FILE, [](const std::wstring &dir_with_back_slant, _wfinddata_t &attrib)->bool
{
std::wcout << dir_with_back_slant << attrib.name << '\n';
return true; //return true to continue, return false to abort searching.
});
return 0;
}
,你會得到下面的輸出:
C:\OpenSSL-Win64\unins000.exe
C:\putty\PAGEANT.EXE
C:\putty\PLINK.EXE
C:\putty\PSCP.EXE
C:\putty\PSFTP.EXE
C:\putty\PUTTY.EXE
C:\putty\PUTTYGEN.EXE
C:\Windows\ampa.exe
C:\Windows\bfsvc.exe
C:\Windows\explorer.exe
C:\Windows\HelpPane.exe
C:\Windows\hh.exe
C:\Windows\notepad.exe
C:\Windows\regedit.exe
C:\Windows\RtCRU64.exe
C:\Windows\SECOH-QAD.exe
C:\Windows\splwow64.exe
C:\Windows\winhlp32.exe
C:\Windows\write.exe
C:\測試\測試.exe
的MAXDEPTH我傳遞給函數爲1 。傳遞-1以搜索所有子目錄。
+0
NTFS和Windows API都支持Unicode。你提出的答案不是。 – IInspectable
+0
@IInspectable謝謝你的建議!該代碼已被修改爲支持Unicode – liuqx
0
這裏是使用用FindFirstFile和FindNextFile唯一可以遞歸找到具有給定擴展名的文件的例子。
#include "stdafx.h"
#include <Windows.h>
#include <atlpath.h>
#include <list>
#include <iostream>
#ifdef _UNICODE
#define cout wcout
#endif
void FindFiles(
const CString& strRootPath,
const CString& strExt,
std::list<CString>& listFiles,
bool bRecursive = true)
{
CString strFileToFind = strRootPath;
ATLPath::Append(CStrBuf(strFileToFind, MAX_PATH), _T("*.*"));
WIN32_FIND_DATA findData = { 0 };
HANDLE hFileFind = ::FindFirstFile(strFileToFind, &findData);
if (INVALID_HANDLE_VALUE != hFileFind)
{
do
{
CString strFileName = findData.cFileName;
if ((strFileName == _T(".")) || (strFileName == _T("..")))
continue;
CString strFilePath = strRootPath;
ATLPath::Append(CStrBuf(strFilePath, MAX_PATH), strFileName);
if (bRecursive && (ATLPath::IsDirectory(strFilePath)))
{
FindFiles(strFilePath, strExt, listFiles);
}
else
{
CString strFoundExt = ATLPath::FindExtension(strFilePath);
if (! strExt.CompareNoCase(strFoundExt))
istFiles.push_back(strFilePath);
}
} while (::FindNextFile(hFileFind, &findData));
::FindClose(hFileFind);
}
}
int main()
{
std::list<CString> listFiles;
FindFiles(_T("e:\\tests"), _T(".cpp"), listFiles);
for (const auto& strFile : listFiles)
std::cout << strFile.GetString() << std::endl;
return 0;
}
注:爲了方便起見,我用ATL的東西像ATL :: CString的和ATLPath功能。在Win32或控制檯應用程序中使用它們沒有任何問題。
相關問題
- 1. 遞歸地查找具有特定擴展名的文件
- 2. 遞歸查找具有特定擴展名的文件
- 3. 具有特定擴展名的文件的遞歸搜索
- 4. 遞歸刪除具有特定擴展名的文件夾
- 5. 遞歸地顯示具有特定擴展名的所有文件
- 6. 移動具有特定文件名和擴展名的文件
- 7. Linux - 如何遞歸搜索具有特定擴展名的文件?
- 8. 在目錄中遞歸搜索具有特定擴展名的文件
- 9. 如何從目錄中遞歸地查找所有文件擴展名?
- 10. 使用find命令查找特定的文件擴展名
- 11. 檢查具有特定擴展名的文件的目錄
- 12. 遞歸刪除具有精確擴展名的隱藏文件
- 13. Python:如何查找具有特定擴展名的所有文件?
- 14. 在Unix中查找具有特定擴展名的所有文件?
- 15. 如何在Android上查找所有具有特定擴展名的文件?
- 16. 使用大小寫和遞歸重命名文件擴展名
- 17. 以遞歸方式查找帶有特定擴展名的圖像
- 18. 遞歸地確定文件夾中所有擴展名的COUNT和SUM
- 19. 是否有替代Windows FindFirstFile/FindNextFile API不搜索短文件名?
- 20. 查找具有特定名稱但具有可變文件擴展名的文件
- 21. 並用FindFirstFile問題FindNextFile
- 22. 在MATLAB中查找並打開一個具有特定擴展名的文件
- 23. 複製具有特定擴展名的文件名的位置
- 24. 查找特定文件名的擴展名
- 25. 如何查找文件名的特定部分/擴展名?
- 26. 刪除具有特定名稱和動態文件擴展名的文件
- 27. 在文件夾中找到一個具有特定擴展名的文件
- 28. Git - 遞歸刪除文件擴展名
- 29. 查找超過特定文件大小的特定擴展名的文件
- 30. 使用FindFirstFile/FindNextFile刪除文件夾中的所有文件的C++代碼
從文檔:_「目錄或路徑以及文件名。文件名可以包含通配符,例如__an__星號(*)或__a__問號(?)。」_ https:// msdn .microsoft.com/en-us/library/windows/desktop/aa364418(v = vs.85).aspx –
是的,我已經看到了。你想說什麼? @RichardCritten – thigi
這真的沒有太大的幫助。所以我想這沒有解決辦法? @RichardCritten – thigi