begin process at 2012 02 05 05:36:41
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Fichiers / Disque

 > CHANGER LA DATE DE CRÉATION/MODIFICATION DE FICHIERS AVEC UN ÉQUIVALENT DU "TOUCH" UNIX/MS-DOS

CHANGER LA DATE DE CRÉATION/MODIFICATION DE FICHIERS AVEC UN ÉQUIVALENT DU "TOUCH" UNIX/MS-DOS


 Information sur la source

Note :
Aucune note
Catégorie :Fichiers / Disque Classé sous :touch, date, fichier, changer, stamp Niveau :Débutant Date de création :16/01/2009 Date de mise à jour :16/01/2009 04:09:41 Vu / téléchargé :5 613 / 183

Auteur : Nicky22

Ecrire un message privé
Commentaire sur cette source (6)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
Salut à tous !

Je poste ici le code source d'un petit utilitaire qui me permet de changer la date de création, de dernière modification ou de dernier accès d'un fichier, sous Windows.
Code écrit en C++/MFC, sous Visual C++ 6.0, pour toutes versions de Windows.
J'ai passé plus de temps à essayer de trouver un programme déjà tout fait ... que de l'écrire !
Coté source, j'ai vu celui de Nebula sur ce site, mais je cherchais un utilitaire un peu plus complet, qui soit à la fois simple et puissant (récursif), et puisse être appelé par un fichier "batch" (.bat), exactement comme le bon vieux touch.exe de MS-DOS... qui est devenu introuvable depuis !
Par rapport aux 2/3 utilitaires essayés, au moins, celui-ci est 100% gratuit, ne plante pas (!) et est donc meilleur pour la planète ;-))
Enfin, franchement, coté utilisation on perd moins de temps à taper la commande dans un shell DOS "à l'ancienne" que d'utiliser une interface fenêtrée et 36 clics à refaire à chaque fois...

Au fait, à quoi ça sert de changer la dates d'un fichier ?
C'est vrai, c'est assez rare... mais voici quelques exemples :
- remettre les photos numériques à la date de la prise de vue (en lisant les infos EXIF)
- taguer un ensemble de fichiers dans un répertoire
- corriger des problèmes de compilation (si la date du fichier projet est plus récente que celle des fichiers .c/.c++, il n'y a plus de compilation incrémentale)
- etc.

Source

  • // FTouch.cpp : Defines the entry point for the console application.
  • //
  • #include "stdafx.h"
  • #ifdef _DEBUG
  • #define new DEBUG_NEW
  • #undef THIS_FILE
  • static char THIS_FILE[] = __FILE__;
  • #endif
  • /////////////////////////////////////////////////////////////////////////////
  • // The one and only application object
  • CWinApp theApp;
  • using namespace std;
  • CString g_sFileFilter;
  • CTime g_aTime=0;
  • CTime g_mTime=0;
  • CTime g_cTime=0;
  • BOOL g_bRecurseDirs=FALSE;
  • // Output date format
  • const char g_szFmt[] = "%Y/%m/%d %H:%M:%S";
  • // Find a substring in a string without case sensitivity
  • LPCTSTR stristr( LPCTSTR string, LPCTSTR strCharSet )
  • {
  • char *pStr=NULL;
  • char szUpBuffer[1024]={0};
  • char szUpCharSet[127]={0};
  • UINT i;
  • for (i=0;i<strlen(string )+1;i++) szUpBuffer [i]=(char)toupper(string[i]);
  • for (i=0;i<strlen(strCharSet)+1;i++) szUpCharSet[i]=(char)toupper(strCharSet[i]);
  • pStr = strstr( szUpBuffer, szUpCharSet );
  • if (!pStr) return NULL;
  • i=pStr-szUpBuffer;
  • pStr=(char *)string+i;
  • return pStr;
  • }
  • // Function that tests
  • BOOL FileMatch(LPCTSTR pszFileName, LPCTSTR pszFileFilter)
  • {
  • int i0,i1,n0,n1,n;
  • char szDrive[2][_MAX_DRIVE]={0};
  • char szDir [2][_MAX_DIR ]={0};
  • char szName [2][_MAX_FNAME]={0};
  • char szExt [2][_MAX_EXT ]={0};
  • char szPath [_MAX_PATH ]={0};
  • LPCTSTR p=NULL;
  • _splitpath(pszFileName , szDrive[0], szDir[0], szName[0], szExt[0]);
  • _splitpath(pszFileFilter, szDrive[1], szDir[1], szName[1], szExt[1]);
  • // Remove the unnecessary point separator
  • if (szExt[0][0]=='.') strcpy(&szExt[0][0],&szExt[0][1]);
  • if (szExt[1][0]=='.') strcpy(&szExt[1][0],&szExt[1][1]);
  • // Check if directories match
  • i0=0; n0=strlen(szDir[0]);
  • i1=0; n1=strlen(szDir[1]);
  • n=max(n0,n1);
  • p=stristr(szDir[0],szDir[1]);
  • if (p) i0=p-szDir[0];
  • if (n1>0) while (i0<n && i1<n)
  • {
  • char c0=toupper(szDir[0][i0]);
  • char c1=toupper(szDir[1][i1]);
  • switch (c1)
  • {
  • case '*' : i0=n ; i1=n ; break;
  • case '?' : i0++ ; i1++ ; break;
  • default : if (c0!=c1) return FALSE;
  • i0++ ; i1++; break;
  • }
  • }
  • // Check if names match
  • i0=0; n0=strlen(szName[0]);
  • i1=0; n1=strlen(szName[1]);
  • n=max(n0,n1);
  • while (i0<n && i1<n)
  • {
  • char c0=toupper(szName[0][i0]);
  • char c1=toupper(szName[1][i1]);
  • switch (c1)
  • {
  • case '*' : i0=n ; i1=n ; break;
  • case '?' : i0++ ; i1++ ; break;
  • default : if (c0!=c1) return FALSE;
  • i0++ ; i1++; break;
  • }
  • }
  • // Check if extensions match
  • i0=0; n0=strlen(szExt[0]);
  • i1=0; n1=strlen(szExt[1]);
  • n=max(n0,n1);
  • while (i0<n && i1<n)
  • {
  • char c0=toupper(szExt[0][i0]);
  • char c1=toupper(szExt[1][i1]);
  • switch (c1)
  • {
  • case '*' : i0=n ; i1=n ; break;
  • case '?' : i0++ ; i1++ ; break;
  • default : if (c0!=c1) return FALSE;
  • i0++ ; i1++; break;
  • }
  • }
  • return TRUE;
  • }
  • // Base function that changes the date stamps of a file
  • BOOL Touch(LPCTSTR pszPath)
  • {
  • CFileStatus status;
  • CFile::GetStatus(pszPath,status);
  • if (g_aTime>0) status.m_atime = g_aTime;
  • if (g_cTime>0) status.m_ctime = g_cTime;
  • if (g_mTime>0) status.m_mtime = g_mTime;
  • CFile::SetStatus(pszPath,status);
  • TRACE("c:%s m:%s a:%s \t%s\n",
  • status.m_ctime.Format(g_szFmt),
  • status.m_mtime.Format(g_szFmt),
  • status.m_atime.Format(g_szFmt), pszPath);
  • return TRUE;
  • }
  • // Recursive function that changes the date stamps of files
  • // matching the file filter. Returns the number of files touched
  • int TouchFiles(LPCTSTR pszPath,LPCTSTR pszFilter)
  • {
  • int n=0;
  • if (!SetCurrentDirectory(pszPath))
  • return n;
  • CFileFind FileFind;
  • if ( !FileFind.FindFile("*.*") )
  • return n;
  • BOOL bNext;
  • do
  • {
  • bNext = FileFind.FindNextFile();
  • if (FileFind.IsDots()) continue;
  • CString sPath = FileFind.GetFilePath();
  • // On ajoute les fichier à la liste des fichiers
  • if (FileFind.IsDirectory())
  • {
  • if (g_bRecurseDirs)
  • n+= TouchFiles(sPath,pszFilter);
  • }
  • else
  • {
  • if (!FileMatch(sPath,pszFilter))
  • continue;
  • if (Touch(sPath)) n++;
  • }
  • } while (bNext);
  • // TRACE("%s : %d datafiles found\n",pszPath,n);
  • return n;
  • }
  • // Utility function that decodes times expressed in the command line
  • // If error, returns CTime(0) <=> Jan. 1st 1970, 01:00:00
  • CTime ExtractTime(LPCTSTR pszParam)
  • {
  • CString s = pszParam;
  • // Replace all exotic characters by whites
  • s.Replace("/"," ");
  • s.Replace(":"," ");
  • s.Replace("_"," ");
  • s.Replace("@"," ");
  • s.Replace(" "," ");
  • // Take current time as default
  • CTime t=CTime::GetCurrentTime();
  • int nYear = t.GetYear();
  • int nMonth= t.GetMonth();
  • int nDay = t.GetDay();
  • int nHour = t.GetHour();
  • int nMin = t.GetMinute();
  • int nSec = t.GetSecond();
  • // Break-up the expression with whites
  • int n = strlen(s);
  • if (!strstr(s," ")) switch(n)
  • {
  • case 0 : break;
  • case 6 :
  • s.Insert( 4," ");
  • s.Insert( 2," ");
  • break;
  • case 8 :
  • s.Insert( 6," ");
  • s.Insert( 4," ");
  • break;
  • case 12 :
  • s.Insert(10," ");
  • s.Insert( 8," ");
  • s.Insert( 6," ");
  • s.Insert( 4," ");
  • s.Insert( 2," ");
  • sscanf(s,"%d",&n);
  • if (n>18 && n<21) // Are the seconds or the century missing here ? Bug if (year%100)=19 or 20 !!!
  • s = s.Left(2)+s.Right(14);
  • break;
  • case 14 :
  • s.Insert(12," ");
  • s.Insert(10," ");
  • s.Insert( 8," ");
  • s.Insert( 6," ");
  • s.Insert( 4," ");
  • break;
  • }
  • // Attribute years, months, days, hours, minutes, seconds
  • n = strlen(s);
  • switch(n)
  • {
  • case 0 : return CTime(nYear,nMonth,nDay,nHour,nMin,nSec);
  • case 1 : return CTime(0);
  • case 8 :
  • case 10:
  • n=sscanf(s,"%d %d %d",&nYear,&nMonth,&nDay);
  • if (n!=3) return CTime(0);
  • break;
  • case 14 :
  • case 16 :
  • n=sscanf(s,"%d %d %d %d %d",&nYear,&nMonth,&nDay,&nHour,&nMin);
  • if (n!=5) return CTime(0);
  • nSec=0;
  • break;
  • case 17 :
  • case 19 :
  • n=sscanf(s,"%d %d %d %d %d %d",&nYear,&nMonth,&nDay,&nHour,&nMin,&nSec);
  • if (n!=6) return CTime(0);
  • break;
  • default :
  • return CTime(0);
  • }
  • // Check validity ranges
  • if (nYear>=0 && nYear<1000 && nYear>50) nYear+=1900; else
  • if (nYear>=0 && nYear<1000 && nYear<50) nYear+=2000;
  • if (nYear < 0 || nYear >3000) return CTime(0);
  • if (nMonth<=0 || nMonth>12) return CTime(0);
  • if (nDay <=1 || nDay >31) return CTime(0);
  • if (nHour < 0 || nHour >23) return CTime(0);
  • if (nMin < 0 || nMin >59) return CTime(0);
  • if (nSec < 0 || nSec >59) return CTime(0);
  • // Build the time value to return
  • t = CTime(nYear,nMonth,nDay,nHour,nMin,nSec);
  • return t;
  • }
  • // Function that tests outputs (examples)
  • CString DateEx(LPCTSTR psz)
  • {
  • CTime t = ExtractTime(psz);
  • CString s=StringFormat("%-20s : %s",psz,t.Format(g_szFmt));
  • return s;
  • }
  • int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  • {
  • int nRetCode = 0;
  • // initialize MFC and print and error on failure
  • if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
  • {
  • // TODO: change error code to suit your needs
  • cerr << _T("Fatal Error: MFC initialization failed") << endl;
  • nRetCode = 1;
  • }
  • else
  • {
  • char drive[_MAX_DRIVE]={0};
  • char dir [_MAX_DIR ]={0};
  • char fname[_MAX_FNAME]={0};
  • char ext [_MAX_EXT ]={0};
  • char szBuffer[MAX_PATH]={0};
  • // Handle command-line flags
  • int nArgc = argc;
  • for (int i=argc-1;i>=1;i--)
  • {
  • LPCTSTR pszArg=argv[i];
  • if ( strlen(pszArg)<2 ) continue;
  • if ( pszArg[0]!='/' && pszArg[0]!='-' )
  • {
  • if ( g_sFileFilter=="") g_sFileFilter = pszArg;
  • }
  • else
  • {
  • BOOL bFound=FALSE;
  • if ( _strnicmp(&pszArg[1],"A=",2)==0) { g_aTime = ExtractTime(&pszArg[3]); if (g_aTime>0) TRACE("aTime=%s\n",g_aTime.Format(g_szFmt)); } else
  • if ( _strnicmp(&pszArg[1],"M=",2)==0) { g_mTime = ExtractTime(&pszArg[3]); if (g_mTime>0) TRACE("mTime=%s\n",g_mTime.Format(g_szFmt)); } else
  • if ( _strnicmp(&pszArg[1],"C=",2)==0) { g_cTime = ExtractTime(&pszArg[3]); if (g_cTime>0) TRACE("cTime=%s\n",g_cTime.Format(g_szFmt)); } else
  • if ( _stricmp (&pszArg[1],"A" )==0) { g_aTime = CTime::GetCurrentTime(); TRACE("aTime=%s\n",g_aTime.Format(g_szFmt)); } else
  • if ( _stricmp (&pszArg[1],"M" )==0) { g_mTime = CTime::GetCurrentTime(); TRACE("mTime=%s\n",g_mTime.Format(g_szFmt)); } else
  • if ( _stricmp (&pszArg[1],"C" )==0) { g_cTime = CTime::GetCurrentTime(); TRACE("cTime=%s\n",g_cTime.Format(g_szFmt)); } else
  • if ( _stricmp (&pszArg[1],"S" )==0) { g_bRecurseDirs = TRUE; } else
  • if (bFound)
  • {
  • // Push command-line params
  • for (int j=i;j<argc;j++)
  • argv[j] = (j<argc-1) ? argv[j+1] : NULL;
  • argc--;
  • }
  • else
  • {
  • TRACE("%s : unknown flag !\n",pszArg);
  • }
  • }
  • }
  • if (g_sFileFilter!="")
  • {
  • char szDrive [_MAX_DRIVE ]={0};
  • char szDir [_MAX_DIR ]={0};
  • char szName [_MAX_FNAME ]={0};
  • char szExt [_MAX_EXT ]={0};
  • char szInitFileDir[_MAX_PATH]={0};
  • char szFileFilter [_MAX_PATH]={0};
  • _splitpath(g_sFileFilter, szDrive, szDir, szName, szExt);
  • _makepath (szInitFileDir, szDrive, szDir, NULL, NULL);
  • _makepath (szFileFilter , NULL, NULL, szName, szExt);
  • if (!szInitFileDir[0]) GetCurrentDirectory(_MAX_PATH,szInitFileDir);
  • if (!szFileFilter[0]) strcpy(szFileFilter,"*.*");
  • TouchFiles(szInitFileDir,szFileFilter);
  • }
  • else
  • {
  • TRACE("File touch utility\n");
  • TRACE("\tUsage : FTouch <filespec> [/C] [/M] [/A] [/C=<date>] [/M=<date>] [/A=<date>] \n");
  • TRACE("\tDateFormats: %s\n",DateEx("20061129175900"));
  • TRACE("\t %s\n",DateEx("20061129"));
  • TRACE("\t %s\n",DateEx("061129"));
  • TRACE("\t %s\n",DateEx("2006_11_29"));
  • TRACE("\t %s\n",DateEx("2006_11_29_17_59_00"));
  • TRACE("\t %s\n",DateEx("2006/11/29_17:59"));
  • TRACE("\t %s\n",DateEx("06/11/29_17:59:00"));
  • }
  • }
  • #ifdef _DEBUG
  • printf("\nPress a key to exit program...");
  • getchar();
  • #endif
  • return nRetCode;
  • }
// FTouch.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// The one and only application object

CWinApp theApp;

using namespace std;

CString	g_sFileFilter;
CTime	g_aTime=0;
CTime	g_mTime=0;
CTime	g_cTime=0;
BOOL	g_bRecurseDirs=FALSE;

// Output date format
const char g_szFmt[] = "%Y/%m/%d %H:%M:%S";


// Find a substring in a string without case sensitivity
LPCTSTR stristr( LPCTSTR string, LPCTSTR strCharSet )
{
	char *pStr=NULL;
	char szUpBuffer[1024]={0};
	char szUpCharSet[127]={0};
	UINT i;
	for (i=0;i<strlen(string    )+1;i++) szUpBuffer [i]=(char)toupper(string[i]);
	for (i=0;i<strlen(strCharSet)+1;i++) szUpCharSet[i]=(char)toupper(strCharSet[i]);
	pStr = strstr( szUpBuffer, szUpCharSet );
	if (!pStr) return NULL;
	i=pStr-szUpBuffer;
	pStr=(char *)string+i;
	return pStr;
}

// Function that tests 
BOOL FileMatch(LPCTSTR pszFileName, LPCTSTR pszFileFilter)
{
	int i0,i1,n0,n1,n;

	char szDrive[2][_MAX_DRIVE]={0};
	char szDir  [2][_MAX_DIR  ]={0};
	char szName [2][_MAX_FNAME]={0};
	char szExt  [2][_MAX_EXT  ]={0};
	char szPath [_MAX_PATH ]={0};
	LPCTSTR p=NULL;

	_splitpath(pszFileName  , szDrive[0], szDir[0], szName[0], szExt[0]);
	_splitpath(pszFileFilter, szDrive[1], szDir[1], szName[1], szExt[1]);
	// Remove the unnecessary point separator
	if (szExt[0][0]=='.') strcpy(&szExt[0][0],&szExt[0][1]);
	if (szExt[1][0]=='.') strcpy(&szExt[1][0],&szExt[1][1]);

	// Check if directories match
	i0=0; n0=strlen(szDir[0]);
	i1=0; n1=strlen(szDir[1]);
	n=max(n0,n1);
	p=stristr(szDir[0],szDir[1]);
	if (p) i0=p-szDir[0];
	if (n1>0) while (i0<n && i1<n)
	{
		char c0=toupper(szDir[0][i0]);
		char c1=toupper(szDir[1][i1]);
		switch (c1)
		{
			case '*' :	i0=n ; i1=n ;	break;
			case '?' :	i0++ ; i1++ ;	break;
			default  :	if (c0!=c1) return FALSE;
						i0++ ; i1++;	break;
		}
	}

	// Check if names match
	i0=0; n0=strlen(szName[0]);
	i1=0; n1=strlen(szName[1]);
	n=max(n0,n1);
	while (i0<n && i1<n)
	{
		char c0=toupper(szName[0][i0]);
		char c1=toupper(szName[1][i1]);
		switch (c1)
		{
			case '*' :	i0=n ; i1=n ;	break;
			case '?' :	i0++ ; i1++ ;	break;
			default  :	if (c0!=c1) return FALSE;
						i0++ ; i1++;	break;
		}
	}

	// Check if extensions match
	i0=0; n0=strlen(szExt[0]);
	i1=0; n1=strlen(szExt[1]);
	n=max(n0,n1);
	while (i0<n && i1<n)
	{
		char c0=toupper(szExt[0][i0]);
		char c1=toupper(szExt[1][i1]);
		switch (c1)
		{
			case '*' :	i0=n ; i1=n ;	break;
			case '?' :	i0++ ; i1++ ;	break;
			default  :	if (c0!=c1) return FALSE;
						i0++ ; i1++;	break;
		}
	}
	return TRUE;
}

// Base function that changes the date stamps of a file
BOOL Touch(LPCTSTR pszPath)
{
	CFileStatus status;
	CFile::GetStatus(pszPath,status);
	if (g_aTime>0) status.m_atime = g_aTime;
	if (g_cTime>0) status.m_ctime = g_cTime;
	if (g_mTime>0) status.m_mtime = g_mTime;
	CFile::SetStatus(pszPath,status);
	TRACE("c:%s m:%s a:%s \t%s\n",
		status.m_ctime.Format(g_szFmt),
		status.m_mtime.Format(g_szFmt),
		status.m_atime.Format(g_szFmt), pszPath);
	return TRUE;
}

// Recursive function that changes the date stamps of files
// matching the file filter. Returns the number of files touched
int TouchFiles(LPCTSTR pszPath,LPCTSTR pszFilter)
{
	int n=0;
	
	if (!SetCurrentDirectory(pszPath))
		return n;

	CFileFind FileFind;
	if ( !FileFind.FindFile("*.*") )
		return n;

	BOOL bNext;
	do
	{
		bNext = FileFind.FindNextFile();
		if (FileFind.IsDots()) continue;
		CString sPath = FileFind.GetFilePath();
		// On ajoute les fichier à la liste des fichiers
		if (FileFind.IsDirectory())
		{
			if (g_bRecurseDirs)
				n+= TouchFiles(sPath,pszFilter);
		}
		else
		{
			if (!FileMatch(sPath,pszFilter))
				continue;
			if (Touch(sPath)) n++;
		}
	} while (bNext);
//	TRACE("%s : %d datafiles found\n",pszPath,n);
	return n;
}

// Utility function that decodes times expressed in the command line
// If error, returns CTime(0) <=> Jan. 1st 1970, 01:00:00
CTime ExtractTime(LPCTSTR pszParam)
{
	CString s = pszParam;

	// Replace all exotic characters by whites
	s.Replace("/"," ");
	s.Replace(":"," ");
	s.Replace("_"," ");
	s.Replace("@"," ");
	s.Replace("  "," ");

	// Take current time as default
	CTime t=CTime::GetCurrentTime();
	int nYear = t.GetYear();
	int nMonth= t.GetMonth();
	int nDay  = t.GetDay();
	int nHour = t.GetHour();
	int nMin  = t.GetMinute();
	int nSec  = t.GetSecond();

	// Break-up the expression with whites
	int n = strlen(s);
	if (!strstr(s," ")) switch(n)
	{
		case 0 : break;
		case 6 :
			s.Insert( 4," ");
			s.Insert( 2," ");
			break;
		case 8 :
			s.Insert( 6," ");
			s.Insert( 4," ");
			break;
		case 12 :
			s.Insert(10," ");
			s.Insert( 8," ");
			s.Insert( 6," ");
			s.Insert( 4," ");
			s.Insert( 2," ");
			sscanf(s,"%d",&n);
			if (n>18 && n<21)	// Are the seconds or the century missing here ? Bug if (year%100)=19 or 20 !!!
				s = s.Left(2)+s.Right(14);
			break;
		case 14 :
			s.Insert(12," ");
			s.Insert(10," ");
			s.Insert( 8," ");
			s.Insert( 6," ");
			s.Insert( 4," ");
			break;
	}

	// Attribute years, months, days, hours, minutes, seconds
	n = strlen(s);
	switch(n)
	{
		case 0 : return CTime(nYear,nMonth,nDay,nHour,nMin,nSec);

		case 1 : return CTime(0);

		case 8 : 
		case 10: 
			n=sscanf(s,"%d %d %d",&nYear,&nMonth,&nDay);
			if (n!=3) return CTime(0);
			break;

		case 14 :
		case 16 :
			n=sscanf(s,"%d %d %d %d %d",&nYear,&nMonth,&nDay,&nHour,&nMin);
			if (n!=5) return CTime(0);
			nSec=0;
			break;

		case 17 :
		case 19 :
			n=sscanf(s,"%d %d %d %d %d %d",&nYear,&nMonth,&nDay,&nHour,&nMin,&nSec);
			if (n!=6) return CTime(0);
			break;

		default :
			return CTime(0);
	}

	// Check validity ranges
	if (nYear>=0 && nYear<1000 && nYear>50) nYear+=1900; else
	if (nYear>=0 && nYear<1000 && nYear<50) nYear+=2000;
	if (nYear < 0 || nYear >3000) return CTime(0);
	if (nMonth<=0 || nMonth>12) return CTime(0);
	if (nDay  <=1 || nDay  >31) return CTime(0);
	if (nHour < 0 || nHour >23) return CTime(0);
	if (nMin  < 0 || nMin  >59) return CTime(0);
	if (nSec  < 0 || nSec  >59) return CTime(0);
	
	// Build the time value to return
	t = CTime(nYear,nMonth,nDay,nHour,nMin,nSec);
	return t;
}

// Function that tests outputs (examples)
CString DateEx(LPCTSTR psz)
{
	CTime t = ExtractTime(psz);
	CString s=StringFormat("%-20s : %s",psz,t.Format(g_szFmt));
	return s;
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int		nRetCode = 0;

	// initialize MFC and print and error on failure
	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
	{
		// TODO: change error code to suit your needs
		cerr << _T("Fatal Error: MFC initialization failed") << endl;
		nRetCode = 1;
	}
	else
	{
		char drive[_MAX_DRIVE]={0};
		char dir  [_MAX_DIR  ]={0};
		char fname[_MAX_FNAME]={0};
		char ext  [_MAX_EXT  ]={0};
		char szBuffer[MAX_PATH]={0};

		// Handle command-line flags
		int nArgc = argc; 
		for (int i=argc-1;i>=1;i--)
		{
			LPCTSTR pszArg=argv[i];
			if ( strlen(pszArg)<2 ) continue;
			if ( pszArg[0]!='/' && pszArg[0]!='-' )
			{
				if ( g_sFileFilter=="")	g_sFileFilter = pszArg;
			}
			else
			{
				BOOL bFound=FALSE;
				if ( _strnicmp(&pszArg[1],"A=",2)==0) { g_aTime = ExtractTime(&pszArg[3]); if (g_aTime>0) TRACE("aTime=%s\n",g_aTime.Format(g_szFmt)); } else
				if ( _strnicmp(&pszArg[1],"M=",2)==0) { g_mTime = ExtractTime(&pszArg[3]); if (g_mTime>0) TRACE("mTime=%s\n",g_mTime.Format(g_szFmt)); } else
				if ( _strnicmp(&pszArg[1],"C=",2)==0) { g_cTime = ExtractTime(&pszArg[3]); if (g_cTime>0) TRACE("cTime=%s\n",g_cTime.Format(g_szFmt)); } else
				if ( _stricmp (&pszArg[1],"A"   )==0) { g_aTime = CTime::GetCurrentTime(); TRACE("aTime=%s\n",g_aTime.Format(g_szFmt)); } else
				if ( _stricmp (&pszArg[1],"M"   )==0) { g_mTime = CTime::GetCurrentTime(); TRACE("mTime=%s\n",g_mTime.Format(g_szFmt)); } else
				if ( _stricmp (&pszArg[1],"C"   )==0) { g_cTime = CTime::GetCurrentTime(); TRACE("cTime=%s\n",g_cTime.Format(g_szFmt)); } else
				if ( _stricmp (&pszArg[1],"S"   )==0) { g_bRecurseDirs = TRUE; } else
				if (bFound)
				{
					// Push command-line params
					for (int j=i;j<argc;j++) 
						argv[j] = (j<argc-1) ? argv[j+1] : NULL;
					argc--;
				}
				else
				{
					TRACE("%s : unknown flag !\n",pszArg);
				}
			}
		}

		if (g_sFileFilter!="")
		{
			char szDrive   [_MAX_DRIVE	]={0}; 
			char szDir	   [_MAX_DIR	]={0}; 
			char szName	   [_MAX_FNAME	]={0}; 
			char szExt	   [_MAX_EXT	]={0};
			char szInitFileDir[_MAX_PATH]={0};
			char szFileFilter [_MAX_PATH]={0};

			_splitpath(g_sFileFilter, szDrive, szDir, szName, szExt);
			_makepath (szInitFileDir, szDrive, szDir, NULL, NULL);
			_makepath (szFileFilter , NULL, NULL, szName, szExt);
			if (!szInitFileDir[0]) GetCurrentDirectory(_MAX_PATH,szInitFileDir);
			if (!szFileFilter[0]) strcpy(szFileFilter,"*.*");

			TouchFiles(szInitFileDir,szFileFilter);
		}
		else
		{
			TRACE("File touch utility\n");
			TRACE("\tUsage      : FTouch <filespec> [/C] [/M] [/A] [/C=<date>] [/M=<date>] [/A=<date>] \n");
			TRACE("\tDateFormats: %s\n",DateEx("20061129175900"));
			TRACE("\t             %s\n",DateEx("20061129"));
			TRACE("\t             %s\n",DateEx("061129"));
			TRACE("\t             %s\n",DateEx("2006_11_29"));
			TRACE("\t             %s\n",DateEx("2006_11_29_17_59_00"));
			TRACE("\t             %s\n",DateEx("2006/11/29_17:59"));
			TRACE("\t             %s\n",DateEx("06/11/29_17:59:00"));
		}
	}

#ifdef _DEBUG
	printf("\nPress a key to exit program...");
	getchar();
#endif

	return nRetCode;
}

 Conclusion

Voilà, c'est mon 1er post.
Je le publie juste pour aider les confrères qui ont les mêmes besoins que moi : retrouver l'équivalent du bon vieux "touch.exe"...

Comme vous le verrez, le code n'est pas révolutionnaire, mais simple et de bon-goût.
Aussi, je pense que ce code intéressera plutôt les débutants.
Désolé, les commentaires sont en anglais (contexte professionnel), mais je pense qu'en tant que développeurs, ça ne doit pas être un problème insurmontable...

Ah, dernière chose : je ne me souvenais plus de la syntaxe de la ligne de commande du programme original, alors j'en ai recréée une qui est simple et puissante.
Le programme lancé seul affiche cette syntaxe de ligne de commande.

Bonne lecture et au plaisir !

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

16 janvier 2009 04:09:41 :
???

 Sources de la même categorie

Source avec Zip Source avec une capture GENERE BMP par lajouad
Source avec Zip Source avec une capture GETIONNAIRE D'UNE BIBLIOTHÉQUE EN C par benzarabel
FONCTION D'ÉDITION DE FICHIER BIT À BIT [C-MULTIPLATEFORME] par lynxtyle
Source avec Zip Source avec une capture UN GESTIONNAIRE DU FICHIER par benzarabel
Source avec Zip COPIE DE FICHIERS PAR RESEAU LOCAL par cczerty

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture GENERE BMP par lajouad
Source avec Zip JOUR DE NAISSANCE par fredg19
Source avec Zip Source avec une capture GETIONNAIRE D'UNE BIBLIOTHÉQUE EN C par benzarabel
FONCTION D'ÉDITION DE FICHIER BIT À BIT [C-MULTIPLATEFORME] par lynxtyle
Source avec Zip CHANGEUR DATE FICHIER (WIN32) par BruNews

Commentaires et avis

Commentaire de Nicky22 le 16/01/2009 04:47:46

Petit bug expliquant le non-fonctionnement, comme vu sur la capture :
il fallait bien évidemment coder :
if (nDay  < 1 || nDay  >31) return CTime(0);
et non pas :
if (nDay  <= 1 || nDay  >31) return CTime(0);

Commentaire de gillardg le 17/01/2009 12:21:07

voir aussi : unxutils

http://sourceforge.net/projects/unxutils

Commentaire de BruNews le 18/01/2009 14:54:58 administrateur CS

Voyons cette fonction:
LPCTSTR stristr(LPCTSTR string, LPCTSTR strCharSet)
{
  char *pStr=NULL;
  char szUpBuffer[1024]={0};
  char szUpCharSet[127]={0};
  UINT i;
  for(i = 0; i < strlen(string) + 1; i++) szUpBuffer[i] = (char)toupper(string[i]);
  for(i = 0; i < strlen(strCharSet) + 1; i++) szUpCharSet[i] = (char)toupper(strCharSet[i]);
  pStr = strstr(szUpBuffer, szUpCharSet);
  if(!pStr) return NULL;
  i = pStr - szUpBuffer;
  pStr = (char*) string+i;
  return pStr;
}

char szUpBuffer[1024]={0};
A quoi sert de forcer un memset() sur des buffers locaux ? à rien puisqu'on va y recopier des chaine qui ont donc un zero teminateur.

for(i = 0; i < strlen(string) + 1; i++) szUpBuffer[i] = (char)toupper(string[i]);
Recalcul strlen() à chaque tour ???
On remplacera par:
char *c, *d;
c = string;
d = szUpBuffer;
while(*c) *d++ = (char) toupper(*c++);
*d = 0;

On obtient donc:
LPCTSTR stristr(LPCTSTR string, LPCTSTR strCharSet)
{
  char szUpBuffer[1024], szUpCharSet[127], *c, *d;
  c = string;
  d = szUpBuffer;
  while(*c) *d++ = (char) toupper(*c++);
  *d = 0;
  c = strCharSet;
  d = szUpCharSet;
  while(*c) *d++ = (char) toupper(*c++);
  *d = 0;
  c = strstr(szUpBuffer, szUpCharSet);
  if(!c) goto strEXIT;
  c = string + (c - szUpBuffer);
strEXIT: return c;
}

Tout l'ensemble du code est à revoir sur ce modèle.

Autre sujet:
Pourquoi employer MFC (ou autre surcouche) pour un mini utilitaire de ce genre ?
Pour cause de MFC, il faut par force un setup pour le distribuer.
Il suffit de remplacer les CString et autres Ctrucmuche par un peu de code pour rendre l'exe indépendant.

Commentaire de Nicky22 le 19/01/2009 03:26:31

Merci BruNews de votre commentaire.

Il est toujours possible de coder de multiples manières... et en fonction du but recherché (intérêt pédagogique, efficacité, robustesse, rapidité d'écriture, lisibilité, portabilité, ré-utilisabilité, etc.), certains choix sont meilleurs que d'autres.

Mais vous énoncez quelques vérités qui ... ne le sont pas :

- écrire char XX[xx]={0} n'équivaut pas à un memset, mais force juste le 1er caractère de la chaine à zéro. En debug, la chaine est de toute façon toute mise à zéro, mais pas en release. J'ai pris cette bonne habitude d'initialiser systématiquement chaque variable il y a longtemps...et ne m'en suis jamais plaint (sauf dans certains cas d'optimisation).
- le strlen dans le test de la boucle "if" ne sera évalué qu'une seule fois.
- Un setup pour déployer les MFC est inutile si on compile le projet en release, mfc42.dll se trouve dans Windows depuis 95/98 (et pas mfc42d.dll, si compilé debug, je vous l'accorde). Enfin, si ça vous inquiète toujours, vous pouvez toujours faire un "static link" avec les .lib des MFC...

Enfin, dans le rayon goûts et couleurs,
- j'aime pas les goto en C, mais à chacun ses marottes !
- OK pour la "surcouche" des MFC, on perd sans doute un peu de perfos (mais sont-elles vraiment requises dans un programme de ce genre ?). Avantages : facilité d'écriture, robustesse et lisibilité (qualités primordiales dans l'industrie). Inconvénient majeur : portabilité.

Pour illustrer ce dernier propos, seriez-vous prêt à réécrire la fonction CString::Replace() juste pour optimiser le code ? D'un point de vue pédagogique, c'est assez intéressant, mais bon...

En tous cas, merci de m'avoir donné l'occasion de débattre avec vous.
Intéressant !
Amicalement / NC

Commentaire de Nicky22 le 19/01/2009 05:19:37

Re-salut BruNews, je n'avais pas vu votre pedigree... bravo !
Vous avez donc certainement de meilleures connaissances que moi en assembleur...
Du coup, j'ai eu un doute sur le nombre d'évaluations de strlen dans la boucle if.
Un petit bout de code de test m'a montré que vous aviez 100% raison.
Il vaut donc mieux remplacer mon code initial
for (i=0;i<strlen(sz);i++) { ... }
par
int n=strlen(sz);
for (i=0;i<n;i++)  { ... }
A+

Commentaire de BruNews le 19/01/2009 11:53:05 administrateur CS

Salut,
Il n'y a que le vieux VS6 pour linker avec MFC42, toute version ultérieure doit fournir un setup ou livrer un exe monumental.

TESTONS:
#define _WIN32_WINNT 0x0600
#define _WIN32_IE 0x0700
#include <windows.h>

char szappname[] = "chrTst";

void fncTst(VOID)
{
  char buf[40] = {0};
  buf[0] = 'a';
  MessageBox(0, buf, szappname, 0);
}

#pragma comment(linker, "/entry:myWinMain")
__declspec(naked) void __stdcall myWinMain()
{
  __asm {
    call    fncTst
    call    fncTst
    push    0
    call    dword ptr ExitProcess
  }
}

LISTING ASM DU COMPILO:
_buf$ = -40
_fncTst@0 PROC
  sub  esp, 40
; 10   :   char buf[40] = {0};
  push  39
  lea  eax, DWORD PTR _buf$[esp+45]
  push  0
  push  eax
  call  _memset
  add  esp, 12
; 11   :   buf[0] = 'a';
; 12   :   MessageBox(0, buf, szappname, 0);
  push  0
  push  OFFSET _szappname
  lea  ecx, DWORD PTR _buf$[esp+48]
  push  ecx
  push  0
  mov  BYTE PTR _buf$[esp+56], 97
  call  DWORD PTR __imp__MessageBoxA@16
  add  esp, 40
  ret  0
_fncTst@0 ENDP

EXE fait 5 Ko et appel memset() sans équivoque.

Avec:
void fncTst(VOID)
{
  char buf[40];
  buf[0] = 'a';
  buf[1] = 0;
  MessageBox(0, buf, szappname, 0);
}

ON OBTIENT:
_buf$ = -40
_fncTst@0 PROC
  sub  esp, 40
; 9    :   char buf[40];
; 10   :   buf[0] = 'a';
; 11   :   buf[1] = 0;
; 12   :   MessageBox(0, buf, szappname, 0);
  push  0
  push  OFFSET _szappname
  lea  eax, DWORD PTR _buf$[esp+48]
  push  eax
  push  0
  mov  BYTE PTR _buf$[esp+56], 97
  mov  BYTE PTR _buf$[esp+57], 0
  call  DWORD PTR __imp__MessageBoxA@16
  add  esp, 40
  ret  0
_fncTst@0 ENDP

EXE = 2.5 Ko et code optimal, y a pas photo.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Changer la date de dernière modification d'un fichier [ par GoldenEye ] Bonjour et bonne année à tous. Je m'étais fait rare ces derniers temps...Existe t'il une API pour changer la date de dernière modification d'un fichie créer un fichier texte dont le nom est une date [ par billybob13 ] J'aimerai cr&#233;er un fichier texte, avec fopen. Mais le nom du fichier doit &#234;tre une date du moment (now).Je ne vois pas comment faire. modifier un fichier en hexadecimal [ par cybermarcel ] bonjours tout le monde !!! la forme ??alors voila je voudrai ouvrire un fichier et changer une valeur mais je voudrai l'ouvrire en hexadecimal et chan problem avec DWORD et FILETIME [ par deck_bsd ] Bonjour, Voila j'ai un probl&#232;me, je voudrai bien sauvegarder dans un fichier la date d'acces d'un fichier r&#233;cup&#233;r&#233; dans une varia Récuperer la date d'un Fichier/Dossier !!! [ par champista ] Chalut,Je suis a la recherche d'une fonction pour recuperer la date d'un fichier ou d'un dossier afficher dans une listview (en MFC) .Je ve afficher e Date de creation d'un fichier [ par squellettor ] J'aimerai recup&#233;rer la date de cr&#233;ation d'un fichier ou d'un repertoire. J'ai trouv&#233; FileAge , mais ca me donne la date de modification problème date [ par phenX ] bonjour, sur mon code j'ai: &nbsp;fprintf(fichier,"%d\t\t", time(&amp;H)); &nbsp;pour afficher la date un fichier texte, et quand j'ouvre le ficier t changer un octet dans un fichier ? [ par supergrey ] Bonjour, je sais le faire mais je souhaiterai connaitre la methode la plus simple pour changer le premier octet d'un fichier, par exemple ajouter 1 a Date Fichier [ par nicompx ] Salut, Pouvez-vous me dire comment récupérer la date de modification d'une fichier. En language C sous linux. Merci &gt;&gt; NiCoMpX &lt;&lt; Tri de fichier dans repertoire selon type d'extension et une partie du nom connu [ par develdelphi ] Bonjour, J'ai un dossier qui contient des fichiers de type .txt et qui sont enregistrés avec un nom dans lequel figure la date et l'heure à la


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 2,855 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales