File mana yang termodifikasi ?

Misalnya saya memiliki 1000 file yang akan saya prosess oleh suatu program, dengan script saya bisa melakukannya seperti ini :

for i=0 to i=1000 { process file ke-i }      

jadi dengan klik sebuat script pekerjaan selesai. Namun, ada beberapa file dari 1000 file tersebut yang berubah / saya modifikasi lagi, sehingga saya perlu mengulang eksekusi script diatas lagi :

for i=0 to i=1000 { process file ke-i }      

Ini tentu tidak efisien dan lama, karena saya mengubah beberapa file, namun 1000 file masih diprocess lagi. Kode yang efisien seharusnya begini :

for i=0 to i=1000 { jika file ke-i ter-modifikasi, maka process file ke-i }    

untuk itu saya perlu suatu program untuk mengecek apakah file ke-i, termodifikasi / tidak. Pekerjaan semacam ini bisa mungkin saja dilakukan dengan python, lua, atau scripting language yang lain. Namun kali ini , (dan waktu2yg lain) , saya suka pakai c/c++ dengan kombinasi Batch , hehehe. Dan, program super simple itu sudah jadi, xediff.exe :d . berikut contoh efisien script yang saya maksud .

[ run_works.bat ]

[sourcecode language=“cpp”] @echo off SET XDIFF=N:\XediProjects\Release\Xediff.exe SET TARGETDIR=D:\test\test for %%i in ( %TARGETDIR%*.* ) do ( call checkmodified.bat %%i ) echo .. Done..

[/sourcecode]

[ checkmodified.bat ]

[sourcecode language=“cpp”] @echo off %XDIFF% %1 > temp.txt set /p XDF= < temp.txt if “%XDF%”==“1” ( @echo ..do something: this file changed %1 %XDF% ) del temp.txt [/sourcecode]

Terdapat 2 file batch, run_works.bat yang memanggil checkmodified.bat. Alasan kenapa jadi 2 file BAT adalah : pipe di BAT tidak bisa bekerja. { apa itu pipe? } . lalu apa yang dilakukan xediff.exe? : xediff.exe menerima argumen berupa file path , dan memberikan output (stdout) ‘1’ & ‘0’  ,file termodifikasi atau tidak . xediff.exe adalah program simple yang mengecek last written time dari suatu file . berikut kodenya [ this is ugly, but i like to share :)    ]

[xediff.exe]

[sourcecode language=“cpp”] // Xedi Xermawan 2013 #include #include #include #include

using namespace std;

bool GetLastWriteTime(HANDLE hFile, SYSTEMTIME& lastaccess,TCHAR* fileLastAccess) { bool isEqual = true; FILETIME ftCreate, ftAccess, ftWrite; SYSTEMTIME stUTC, stLocal; // Retrieve the file times for the file. if (!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite)) return false; // Convert the last-write time to local time. FileTimeToSystemTime(&ftWrite, &stUTC); SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal); if(stLocal.wMonth != lastaccess.wMonth || stLocal.wDay!= lastaccess.wDay || stLocal.wYear!= lastaccess.wYear || stLocal.wHour!= lastaccess.wHour || stLocal.wMinute!= lastaccess.wMinute || stLocal.wSecond!= lastaccess.wSecond ) { isEqual = false; } fstream fileOut(fileLastAccess,std::ios::out|std::ios::binary); const char* c=reinterpret_cast(&stLocal); fileOut.write(c,sizeof(stLocal)); fileOut.close(); return isEqual; }

bool GetLastTimeAccess(SYSTEMTIME& ret, TCHAR* fileLastAccess) { fstream fileIn(fileLastAccess,std::ios::in | std::ios::binary); if(!fileIn) { return false; } fileIn.read( reinterpret_cast(&ret), sizeof(ret) ); fileIn.close(); return true; }

void BreakPath(TCHAR* filepath, TCHAR* filedir, TCHAR* filename) { unsigned int i=0,lastSlash=0; TCHAR buff[MAX_PATH]; while(*filepath !=“) { buff[i] = *filepath; if(*filepath++==’\’) lastSlash=i; i++; } buff[i]=’\0’; i=0; while(i < lastSlash+1) { *filedir++ = buff[i++]; } *filedir++ =‘.’; *filedir++ =‘x’; *filedir++ =’d’; *filedir++ =‘f’; *filedir++ =’\’; *filedir=“; while(buff[i] !=“) { *filename++ = buff[i++]; } *filename =’\0’; }

void FixPath(TCHAR* filedir, TCHAR* filename,TCHAR* filenamefix) { while(*filedir !=“) { *filenamefix++ = *filedir++; } while(*filename !=“) { *filenamefix++ = *filename++; } *filenamefix++=‘.’; *filenamefix++=‘x’; *filenamefix++=’d’; *filenamefix++=‘i’; *filenamefix++=‘f’; *filenamefix++=‘f’; *filenamefix=’\0’; }

int _tmain(int argc, TCHAR argv[]) { HANDLE hFile; int retVal = 1; if( argc != 2 ) { retVal = 1; printf(“%d”,retVal); return retVal; } TCHAR filepath = argv[1]; TCHAR filedir[MAX_PATH]; TCHAR filename[MAX_PATH]; TCHAR filename_fix[MAX_PATH]; SYSTEMTIME lastaccessnoted; BreakPath(filepath,filedir,filename); CreateDirectory( filedir , NULL ); FixPath(filedir,filename,filename_fix); GetLastTimeAccess(lastaccessnoted, filename_fix ); hFile = CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL,OPEN_EXISTING, 0, NULL);

if(hFile == INVALID_HANDLE_VALUE)   {
    retVal = 1;
    printf("%d",retVal);
    return retVal;;
}
if( (GetLastWriteTime( hFile, lastaccessnoted, filename_fix ) ))     {
    retVal = 0; // file same // not modified
    printf("%d",retVal);
    return retVal;;
}
CloseHandle(hFile);
printf("%d",retVal);
return retVal;

} [/sourcecode]

// edi ermawan // yogjakarta 27042013

// keywords: file modified  check, c++, c, Batch, incremental build

comments powered by Disqus