From 20bec3cf6b0ea573c9e1be7784a9e9e430424e82 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Wed, 17 Oct 2001 18:30:10 +0000 Subject: [PATCH] Implemented useful rename command. svn path=/trunk/; revision=2302 --- rosapps/cmd/cmd.rc | 2 +- rosapps/cmd/cmdver.h | 2 +- rosapps/cmd/ren.c | 265 ++++++++++++++++++++++++++++++++++++++----- rosapps/cmd/ver.c | 2 +- 4 files changed, 241 insertions(+), 30 deletions(-) diff --git a/rosapps/cmd/cmd.rc b/rosapps/cmd/cmd.rc index ad19057309c..18b041ea289 100644 --- a/rosapps/cmd/cmd.rc +++ b/rosapps/cmd/cmd.rc @@ -26,7 +26,7 @@ BEGIN VALUE "FileVersion", CMD_VER_RC VALUE "InternalName", "cmd\0" VALUE "OriginalCopyright", "Copyright (C) 1994-1998 Tim Norman and others\0" - VALUE "LegalCopyright", "Copyright (C) 1998-2000 Eric Kohl\0" + VALUE "LegalCopyright", "Copyright (C) 1998-2001 Eric Kohl and others\0" VALUE "OriginalFilename", "cmd.exe\0" VALUE "ProductName", RES_STR_PRODUCT_NAME VALUE "ProductVersion", RES_STR_PRODUCT_VERSION diff --git a/rosapps/cmd/cmdver.h b/rosapps/cmd/cmdver.h index 45ec120e2a5..93ed1b8f446 100644 --- a/rosapps/cmd/cmdver.h +++ b/rosapps/cmd/cmdver.h @@ -1,2 +1,2 @@ -#define CMD_VER "0.1.1" +#define CMD_VER "0.1.2" #define CMD_VER_RC CMD_VER"\0" diff --git a/rosapps/cmd/ren.c b/rosapps/cmd/ren.c index b8976e395f0..8a7f2f6c447 100644 --- a/rosapps/cmd/ren.c +++ b/rosapps/cmd/ren.c @@ -12,6 +12,9 @@ * * 20-Jan-1999 (Eric Kohl * Unicode and redirection safe! + * + * 17-Oct-2001 (Eric Kohl + * Implemented basic rename code. */ #include "config.h" @@ -21,50 +24,258 @@ #include #include #include +#include #include "cmd.h" +#include "batch.h" + +enum +{ + REN_ATTRIBUTES = 0x001, /* /A : not implemented */ + REN_ERROR = 0x002, /* /E */ + REN_NOTHING = 0x004, /* /N */ + REN_PROMPT = 0x008, /* /P : not implemented */ + REN_QUIET = 0x010, /* /Q */ + REN_SUBDIR = 0x020, /* /S */ + REN_TOTAL = 0x040, /* /T */ +}; + /* - * simple file rename internal command. + * file rename internal command. * */ INT cmd_rename (LPTSTR cmd, LPTSTR param) { - LPTSTR *arg; - INT argc; + LPTSTR *arg = NULL; + INT args = 0; + INT nEvalArgs = 0; /* nunber of evaluated arguments */ + DWORD dwFlags = 0; + DWORD dwFiles = 0; /* number of renamedd files */ + INT i; + LPTSTR srcPattern = NULL; + LPTSTR dstPattern = NULL; + TCHAR dstFile[MAX_PATH]; + BOOL bDstWildcard = FALSE; - if (!_tcsncmp (param, _T("/?"), 2)) + LPTSTR p,q,r; + + HANDLE hFile; + WIN32_FIND_DATA f; + + if (!_tcsncmp(param, _T("/?"), 2)) + { + ConOutPuts(_T("Renames a file/directory or files/directories.\n" + "\n" + "RENAME [/E /N /P /Q /S /T] old_name ... new_name\n" + "REN [/E /N /P /Q /S /T] old_name ... new_name\n" + "\n" + " /E No eror messages.\n" + " /N Nothing.\n" + " /P Prompts for confirmation before renaming each file.\n" + " (Not implemented yet!)\n" + " /Q Quiet.\n" + " /S Rename subdirectories.\n" + " /T Display total number of renamed files.\n" + "\n" + "Note that you cannot specify a new drive or path for your destination. Use\n" + "the MOVE command for that purpose.")); + return(0); + } + + /* split the argument list */ + arg = split(param, &args); + + if (args < 2) + { + if (!(dwFlags & REN_ERROR)) + error_req_param_missing(); + freep(arg); + return(1); + } + + /* read options */ + for (i = 0; i < args; i++) + { + if (*arg[i] == _T('/')) { - ConOutPuts (_T("Renames a file/directory or files/directories.\n" - "\n" - "RENAME [drive:][path][directoryname1 | filename1] [directoryname2 | filename2]\n" - "REN [drive:][path][directoryname1 | filename1] [directoryname2 | filename2]\n" - "\n" - "Note that you cannot specify a new drive or path for your destination. Use\n" - "the MOVE command for that purpose.")); - return 0; + if (_tcslen(arg[i]) >= 2) + { + switch (_totupper(arg[i][1])) + { + case _T('E'): + dwFlags |= REN_ERROR; + break; + + case _T('N'): + dwFlags |= REN_NOTHING; + break; + + case _T('P'): + dwFlags |= REN_PROMPT; + break; + + case _T('Q'): + dwFlags |= REN_QUIET; + break; + + case _T('S'): + dwFlags |= REN_SUBDIR; + break; + + case _T('T'): + dwFlags |= REN_TOTAL; + break; + } + } + nEvalArgs++; + } + } + + /* keep quiet within batch files */ + if (bc != NULL) + dwFlags |= REN_QUIET; + + /* there are only options on the command line --> error!!! */ + if (args < nEvalArgs + 2) + { + if (!(dwFlags & REN_ERROR)) + error_req_param_missing(); + freep(arg); + return(1); + } + + /* get destination pattern */ + for (i = 0; i < args; i++) + { + if (*arg[i] == _T('/')) + continue; + dstPattern = arg[i]; + } + + if (_tcschr(dstPattern, _T('*')) || _tcschr(dstPattern, _T('?'))) + bDstWildcard = TRUE; + + /* enumerate source patterns */ + for (i = 0; i < args; i++) + { + if (*arg[i] == _T('/') || arg[i] == dstPattern) + continue; + + srcPattern = arg[i]; + +#ifdef _DEBUG + ConErrPrintf(_T("\n\nSourcePattern: %s\n"), srcPattern); + ConErrPrintf(_T("DestinationPattern: %s\n"), dstPattern); +#endif + + hFile = FindFirstFile(srcPattern, &f); + if (hFile == INVALID_HANDLE_VALUE) + { + if (!(dwFlags & REN_ERROR)) + error_file_not_found(); + continue; } - /* split the argument list */ - arg = split (param, &argc); - - if (argc != 2) + do { - freep (arg); - error_too_many_parameters (param); - return 1; + /* ignore "." and ".." */ + if (!_tcscmp (f.cFileName, _T(".")) || + !_tcscmp (f.cFileName, _T(".."))) + continue; + + /* do not rename hidden or system files */ + if (f.dwAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) + continue; + + /* do not rename directories when the destination pattern contains + * wildcards, unless option /S is used */ + if ((f.dwAttributes & FILE_ATTRIBUTE_DIRECTORY) + && bDstWildcard + && !(dwFlags & REN_SUBDIR)) + continue; + +#ifdef _DEBUG + ConErrPrintf(_T("Found source name: %s\n"), f.cFileName); +#endif + + /* build destination file name */ + p = f.cFileName; + q = dstPattern; + r = dstFile; + while(*q != 0) + { + if (*q == '*') + { + q++; + while (*p != 0 && *p != *q) + { + *r = *p; + p++; + r++; + } + } + else if (*q == '?') + { + q++; + if (*p != 0) + { + *r = *p; + p++; + r++; + } + } + else + { + *r = *q; + if (*p != 0) + p++; + q++; + r++; + } + } + *r = 0; + +#ifdef _DEBUG + ConErrPrintf(_T("DestinationFile: %s\n"), dstFile); +#endif + + if (!(dwFlags & REN_QUIET) && !(dwFlags & REN_TOTAL)) + ConOutPrintf(_T("%s -> %s\n"), f.cFileName, dstFile); + + /* rename the file */ + if (!(dwFlags & REN_NOTHING)) + { + if (MoveFile(f.cFileName, dstFile)) + { + dwFiles++; + } + else + { + if (!(dwFlags & REN_ERROR)) + ConErrPrintf(_T("MoveFile() failed. Error: %lu\n"), GetLastError()); + } + } } + while (FindNextFile(hFile, &f)); + FindClose(hFile); + } - if (!MoveFile (arg[0], arg[1])) - { - ConErrPuts (_T("rename")); - freep (arg); - return 1; - } + if (!(dwFlags & REN_QUIET)) + { + if (dwFiles == 1) + ConOutPrintf(_T(" %lu file renamed\n"), + dwFiles); + else + ConOutPrintf(_T(" %lu files renamed\n"), + dwFiles); + } - freep (arg); + freep(arg); - return 0; + return(0); } #endif + +/* EOF */ diff --git a/rosapps/cmd/ver.c b/rosapps/cmd/ver.c index 51d0d6aa50d..333f5672b9d 100644 --- a/rosapps/cmd/ver.c +++ b/rosapps/cmd/ver.c @@ -128,7 +128,7 @@ INT cmd_ver (LPTSTR cmd, LPTSTR param) "\n" "ReactOS version written by:\n" " Eric Kohl Emanuele Aliberti\n" - " Paolo Pantaleo\n")); + " Paolo Pantaleo Phillip Susi\n")); } else {