Jump to content



Σπαζοκεφαλιά με Created και Modified Date σε αρχεία.


cherryman

Recommended Posts

Λοιπόν,

λίγο μπερδεμένο το ζήτημα.

Κάποια στιγμή φίλος μου χρησιμοποίησε έναν δίσκο μου για να μεταφέρει έναν μεγάλο όγκο αρχείων ώστε να τα ξαναμεταφέρει στο δικό του pc αφότου επανεγκατέστησε τα win.

Η μεταφορά αυτή είχε σαν αποτέλεσμα να αλλάξουν οι "Created" και "Modified" ημερομηνίες θέση. Δηλαδή σαν Created Date εμφανίζεται η Modified. Η μέρα δηλαδή που αλλάξανε "στέγη" τα αρχεία. Και σαν Modified εμφανίζεται η Created. Δηλαδή η μέρα που πραγματικά δημιουργηθήκανε τα αρχεία.

Στο internet υπάρχουν αρκετά προγράμματα που κάνουν μαζική αλλαγή των ημερομηνιών. Τους λες δηλαδή ότι θέλεις όλα να πάρουν την τάδε ημερομηνία. Εμείς δεν θέλουμε αυτό όμως. Θέλουμε να τουμπάρουμε τις ημερομηνίες σε όλα τα αρχεία. Η Created να πάρει τη θέση της Modified σε κάθε αρχείο ξεχωριστά.

Ευχαριστώ.

Link to comment
Share on other sites

Για δοκίμασε αυτό...

Πριν κάνεις οτιδήποτε, δοκίμασε το σε ένα δικό σου temp φάκελο και δες ότι το κάνει σωστά... ρίξε τυχαία αρχεία, βάλε και το exe εκεί και τρέχ' το...

Μετά θα πρέπει να το τρέξεις σε κάθε φάκελο ξεχωριστά, δεν το έχω κάνει recursive επίτηδες, για αποφυγή προβλημάτων...

Και το source code για όποιον θέλει...


#include "windows.h"
#include <io.h>
#include <string>
#include <vector>
#include <list>
#include <iostream>

using namespace std;

std::wstring s2ws(const std::string& s)
{
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}

std::string ws2s(const std::wstring& s)
{
int len;
int slength = (int)s.length() + 1;
len = WideCharToMultiByte(CP_ACP, 0, s.c_str(), slength, 0, 0, 0, 0);
char* buf = new char[len];
WideCharToMultiByte(CP_ACP, 0, s.c_str(), slength, buf, len, 0, 0);
std::string r(buf);
delete[] buf;
return r;
}

BOOL SwapDates(string fName)
{
HANDLE hFile;
char tmpStr[1500];
std::wstring w_fName = s2ws(fName);

hFile = CreateFile(w_fName.c_str(), GENERIC_WRITE, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if (hFile != INVALID_HANDLE_VALUE) {

FILETIME ftCreate, ftAccess, ftWrite;
SYSTEMTIME stUTC, stLocal;

if (!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite))
return FALSE;

SetFileTime(hFile, &ftWrite, //creation
&ftCreate, //last access
&ftCreate); //last write

FileTimeToSystemTime(&ftWrite, &stUTC);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

sprintf(tmpStr, "%02d/%02d/%d,%02d:%02d",
stLocal.wDay, stLocal.wMonth, stLocal.wYear,
stLocal.wHour, stLocal.wMinute);

cout << tmpStr << " <-> ";

FileTimeToSystemTime(&ftCreate, &stUTC);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

sprintf(tmpStr, "%02d/%02d/%d,%02d:%02d",
stLocal.wDay, stLocal.wMonth, stLocal.wYear,
stLocal.wHour, stLocal.wMinute);

cout << tmpStr << endl;
}
else {
cout << " failed." << endl;
return FALSE;
}

return TRUE;
}


void ProcessDirectory(string path)
{
struct _finddatai64_t data;
string fname = path + "\\*.*";
long h = _findfirsti64(fname.c_str(),&data);
if(h >= 0)
{
do {
if( (data.attrib & _A_SUBDIR) )
{
//better skip
}
else
{
cout << "[" << data.name << "] : ";
SwapDates(data.name);

}
}while( _findnexti64(h,&data) == 0);
_findclose(h);

}
}

int _tmain(int argc, _TCHAR* argv[])
{
//Get current path
wchar_t w_path[MAX_PATH];

DWORD len;
BOOL success;
len = GetCurrentDirectory(MAX_PATH, w_path);
cout << "Jaco :p" << endl << "Start processing inside running DIR..." << endl;
cout << "[Filename] : creation date <-> modification date" << endl << endl;
if (len == 0)
{
cout << "Can't get current directory: " << GetLastError() << endl;
}
else
{
string path = ws2s(w_path);
ProcessDirectory(path);
}

cout << endl << "Finished." << endl << "Press Enter to exit." << endl;
char a = getchar();
return 0;
}
#include "stdafx.h"

Link to comment
Share on other sites

Ευχαριστώ πολύ για τον χρόνο σου.

Θα το κάνω wrap σε ένα python script ή μέσω cygwin για να το τρέξω recursively στο root των αρχείων μου.

Μου κάνει εντύπωση που δεν βγήκα αρκετά προγράμματα στο internet με ικανοποιητικές παραμέτρους. Σχεδόν όλα είναι μέσω UI με τα τελείως βασικά.

Το dirdate είναι καλό αλλά θέλει λεφτά μετά από τα πρώτα 1000 αρχεία.

DirDate - Change file dates and times (timestamps)

Πριν λίγο βρήκα και αυτό που ίσως κάνει την δουλειά.

Touch for Windows - CodeProject

Ευχαριστώ και πάλι!!!

=]

Link to comment
Share on other sites

τι είναι αυτό το recursive που είπες

Εννοώ ότι δεν μπαίνει μέσα σε sub-directories, αλλά μένει μόνο στο πρώτο επίπεδο, δηλαδή το directory από το οποίο το έτρεξες... το έκανα για ασφάλεια για μην πειράζει οτιδήποτε δεν βλέπεις πραγματικά μπροστά σου...

@Ch3, είναι με winapi, οπότε θα παίξει μόνο σε windows... με κάποιο batch script από το shell των windows, είναι εύκολο να το κάνεις να διεισδύει...

Link to comment
Share on other sites

Οκ, κατάφερα να το τρέξω recursively σε πολλά directories, αλλά δυστυχώς το print Finished μαζί με press Enter to Exit διακόπτει την διαδικασία.

Θα προσπαθήσω να το σετάρω κάποιον C++ compiler για να κάνω το ξανακάνω compile χωρίς τις τελευταίες γραμμές.

cout << endl << "Finished." << endl << "Press Enter to exit." << endl;

char a = getchar();

return 0;

Με κάποιο αντίστοιχο τρόπο μπορείς να αλλάξεις και την ημερομηνία σε folders; Θα ήθελα το κάθε folder να έχει την ημερομηνία του τελευταίου αρχείου που περιέχει

Link to comment
Share on other sites

Jaco, με visual studio το έκανες compile;

Προσπαθώ με τον free της borland 5.5. Στην αρχή παραπονιόταν που δεν έβρισκε το stdafx.h

Το βρήκα και το πρόσθεσαν από κάτι άλλα προγράμματα που έτυχε να το έχουν και τώρα μου βγάζει μπόλικα errors:

D:\myStuff\Dev\cpp\dateChanger>bcc32 dateChanger.cpp

Borland C++ 5.5.1 for Win32 Copyright © 1993, 2000 Borland

dateChanger.cpp:

Error E2034 dateChanger.cpp 42: Cannot convert 'const wchar_t *' to 'const char

*' in function SwapDates(string)

Error E2342 dateChanger.cpp 42: Type mismatch in parameter 'lpFileName' (wanted

'const char *', got 'const wchar_t *') in function SwapDates(string)

Error E2285 dateChanger.cpp 87: Could not find a match for '_findfirsti64(const

char *,_finddatai64_t *)' in function ProcessDirectory(string)

Error E2034 dateChanger.cpp 114: Cannot convert 'wchar_t *' to 'char *' in funct

ion main(int,char * *)

Error E2342 dateChanger.cpp 114: Type mismatch in parameter 'lpBuffer' (wanted '

char *', got 'wchar_t *') in function main(int,char * *)

Warning W8004 dateChanger.cpp 130: 'a' is assigned a value that is never used in

function main(int,char * *)

Warning W8057 dateChanger.cpp 130: Parameter 'argc' is never used in function ma

in(int,char * *)

Warning W8057 dateChanger.cpp 130: Parameter 'argv' is never used in function ma

in(int,char * *)

*** 5 errors in Compile ***

Καμιά ιδέα;

Link to comment
Share on other sites

Μπορείς να κατεβάσεις το visual studio express που είναι δωρεάν, με τον compiler της ms το έκανα compile... Αν θες το απόγευμα, που θα μπορώ θα το κάνω ξανά και θα το ανεβάσω, διαφορετικά κατέβασε το express...

Με τον borland θα πρέπει να μπορείς να το κάνεις, αρκεί να βγάλεις το Header που χτυπάει... αυτός που έχεις, μάλλον δεν υποστηρίζει τα unicodes, γι' αυτό σου χτυπάει στα w_char κλπ...

Link to comment
Share on other sites

Φίλε Jaco σε ευχαριστώ πολύ!

Έβαλα τελικά το visual studio express όπως είπες και το ξανά-έκανα compile μιας και χρειάστηκε να προσθέσω έναν έλεγχο ώστε να μην αλλάζει τις ημερομηνίες στα αρχεία που έχουν πιο πρόσφατη modify date από creation.

Πάλεψα αρκετές ώρες με τους compilers και C++ μιας και ίσα ίσα που σκαμπάζω... αλλά τελικά κατάφερα και έβαλα το φωτογραφικό μου αρχείο μου σε μια τάξη.

=]

Link to comment
Share on other sites

Συγνώμη για την καθυστέρηση. Ορίστε τα εκτελέσιμα, ο κώδικας και το recursive python script που τρέχω για να κάνω την μετατροπή σε πολλούς φακέλους.

Το fileDateSwap κάνει swap το creation με το modify date, ενώ το fileDateCopy, αντιγράφει το creation date στα άλλα δύο πεδία. Και τα δύο λειτουργούν εάν και εφόσον η καινούργια ημερομηνία είναι η πιο παλιά από τις δύο.

Από περιέργεια Jaco, πως και το δικό σου .exe είναι πάνω από 100k ενώ το δικό μου μόνο 14k;

Έχει να κάνει με κάποια επιλογή στο compile;

Σε ευχαριστώ και πάλι για την βοήθεια. Πραγματικά έσωσες!

fileDateCopy.exe

fileDateSwap.exe

#include "stdafx.h"

#include "windows.h"

#include <io.h>

#include <string>

#include <vector>

#include <list>

#include <iostream>

using namespace std;

std::wstring s2ws(const std::string& s)

{

int len;

int slength = (int)s.length() + 1;

len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);

wchar_t* buf = new wchar_t[len];

MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);

std::wstring r(buf);

delete[] buf;

return r;

}

std::string ws2s(const std::wstring& s)

{

int len;

int slength = (int)s.length() + 1;

len = WideCharToMultiByte(CP_ACP, 0, s.c_str(), slength, 0, 0, 0, 0);

char* buf = new char[len];

WideCharToMultiByte(CP_ACP, 0, s.c_str(), slength, buf, len, 0, 0);

std::string r(buf);

delete[] buf;

return r;

}

BOOL SwapDates(string fName)

{

HANDLE hFile;

char tmpStr[1500];

std::wstring w_fName = s2ws(fName);

hFile = CreateFile(w_fName.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if (hFile != INVALID_HANDLE_VALUE)

{

FILETIME ftCreate, ftAccess, ftWrite;

SYSTEMTIME stUTC, stLocal;

if (!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite))

return FALSE;

if( CompareFileTime(&ftCreate, &ftWrite) == 1 )

{

cout << " Swaping dates\t : " << fName << endl;

SetFileTime(hFile, &ftWrite, //creation

&ftCreate, //last access

&ftCreate); //last write

}

else

cout << " No change \t : " << fName << endl;

}

else

{

cout << " Failed \t\t :" << fName << endl;

return FALSE;

}

return TRUE;

}

void ProcessDirectory(string path)

{

struct _finddatai64_t data;

string fname = path + "\\*.*";

long h = _findfirsti64(fname.c_str(),&data);

if(h >= 0)

{

do {

if( (data.attrib & _A_SUBDIR) )

{

//better skip

}

else

{

//cout << data.name << "\t\t\t : ";

SwapDates(data.name);

}

}while( _findnexti64(h,&data) == 0);

_findclose(h);

}

}

int _tmain(int argc, _TCHAR* argv[])

{

//Get current path

wchar_t w_path[MAX_PATH];

DWORD len;

BOOL success;

len = GetCurrentDirectory(MAX_PATH, w_path);

if (len == 0)

{

cout << "Can't get current directory: " << GetLastError() << endl;

}

else

{

string path = ws2s(w_path);

cout << endl << path << endl;

ProcessDirectory(path);

}

//cout << endl << endl << "Finished." << endl << "Press Enter to exit." << endl;

//char a = getchar();

return 0;

}

import os

def listFolders(dir):

folders = []

for item in os.listdir(dir):

if os.path.isdir(os.path.join(dir,item)):

folders.append(os.path.join(dir,item))

for subFolder in folders:

subItems = listFolders(subFolder)

for subItem in subItems:

folders.append( subItem )

return folders

list = []

list = listFolders("D:\\myStuff\\My Pictures\\digi\\")

print "==========="

print "==========="

for folder in list:

os.chdir(folder)

os.system("FileDatecopy.exe")

Link to comment
Share on other sites

Έχω κάνει static build και δεν χρησιμοποιώ manifests, οπότε να είναι unmanaged και είναι native code αντί να είναι κάποια ενδιάμεση assembly που χρησιμοποιεί η .net πχ...

Αυτό που χάνεις στο native code είναι σε μέγεθος, γιατί σου προκύπτει μεγαλύτερο αρχείο, ενώ κερδίζεις στο ότι το exe σου θα παίξει σε όλα τα windows, ανεξάρτητα από το αν έχουν εγκατεστημένα τα libraries που έχεις χρησιμοποιήσει... Στο dynamic link θα πρέπει να δώσεις και τα dynamic libraries μαζί με το exe σου και να κάνεις register στο λειτουργικό, αν δεν τα έχει ήδη... Στην δεύτερη περίπτωση μπορεί να μπλέξεις με ασυμβατότητες και το γνωστό dll/manifest hell, αν και τώρα με το SxS (side by side assembly) τα περισσότερα από αυτά τα προβλήματα έχουν διορθωθεί, αλλά και πάλι προτιμώ όποτε μπορώ το static γιατί γλυτώνεις τα manifests και το versioning στις βιβλιοθήκες... με το static ότι γράψεις και παίζει σωστά, θα παίζει για πάντα σωστά ανεξάρτητα αν οι βιβλιοθήκες που χρησιμοποιεί αλλάζουν, γιατί θα έχει ενσωματώσει την έκδοσή τους (την assembly) μέσα του το ίδιο το πρόγραμμα...

Γενικά δεν υπάρχει σωστό/λάθος στο staic/dynamic build, έχει να κάνει κυρίως με την εφαρμογή, αλλά και μετά με το γούστο του καθενός... Υπάρχουν πχ projects, που απλά δεν μπορούν να γίνουν χωρίς dynamic linking και άλλα που δεν μπορούν να γίνουν χωρίς static... είναι περισσότερο και θέμα πείρας νομίζω...

Για να αλλάξεις μεταξύ dynamic και static linking, με την προϋπόθεση ότι το υποστηρίζουν και οι βιβλιοθήκες, πρέπει να αλλάξεις στον compiler τα flags σε /MTd για debugging και /MT για release όταν θες static και σε /MDd για debugging και /MD για release όταν θες dynamic... Επίσης αν θες να μην δημιουργεί manifest assemblies, τότε το απενεργοποιείς από τον linker... αυτά θα τα βρεις στα project properties...

Τέλος για την συγκεκριμένη μόνο περίπτωση, επειδή όλα είναι kernel calls, πραγματικά δεν έχει σημασία αν θα το κάνεις static ή dynamic...

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Δημιουργία...

Important Information

Ο ιστότοπος theLab.gr χρησιμοποιεί cookies για να διασφαλίσει την καλύτερη εμπειρία σας κατά την περιήγηση. Μπορείτε να προσαρμόσετε τις ρυθμίσεις των cookies σας , διαφορετικά θα υποθέσουμε ότι είστε εντάξει για να συνεχίσετε.