Implemented useful rename command.
authorEric Kohl <eric.kohl@reactos.org>
Wed, 17 Oct 2001 18:30:10 +0000 (18:30 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Wed, 17 Oct 2001 18:30:10 +0000 (18:30 +0000)
svn path=/trunk/; revision=2302

rosapps/cmd/cmd.rc
rosapps/cmd/cmdver.h
rosapps/cmd/ren.c
rosapps/cmd/ver.c

index ad19057..18b041e 100644 (file)
@@ -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
index 45ec120..93ed1b8 100644 (file)
@@ -1,2 +1,2 @@
-#define CMD_VER      "0.1.1"
+#define CMD_VER      "0.1.2"
 #define CMD_VER_RC   CMD_VER"\0"
index b8976e3..8a7f2f6 100644 (file)
@@ -12,6 +12,9 @@
  *
  *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>
  *        Unicode and redirection safe!
+ *
+ *    17-Oct-2001 (Eric Kohl <ekohl@rz.online.de>
+ *        Implemented basic rename code.
  */
 
 #include "config.h"
 #include <windows.h>
 #include <tchar.h>
 #include <string.h>
+#include <ctype.h>
 
 #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;
+
+  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 (!_tcsncmp (param, _T("/?"), 2))
+  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);
+    }
 
-       /* split the argument list */
-       arg = split (param, &argc);
+  /* get destination pattern */
+  for (i = 0; i < args; i++)
+    {
+      if (*arg[i] == _T('/'))
+       continue;
+      dstPattern = arg[i];
+    }
 
-       if (argc != 2)
+  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)
        {
-               freep (arg);
-               error_too_many_parameters (param);
-               return 1;
+         if (!(dwFlags & REN_ERROR))
+           error_file_not_found();
+         continue;
        }
 
-       if (!MoveFile (arg[0], arg[1]))
+      do
        {
-               ConErrPuts (_T("rename"));
-               freep (arg);
-               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);
+    }
 
-       freep (arg);
+  if (!(dwFlags & REN_QUIET))
+    {
+       if (dwFiles == 1)
+         ConOutPrintf(_T("    %lu file renamed\n"),
+                      dwFiles);
+       else
+         ConOutPrintf(_T("    %lu files renamed\n"),
+                      dwFiles);
+    }
 
-       return 0;
+  freep(arg);
+
+  return(0);
 }
 
 #endif
+
+/* EOF */
index 51d0d6a..333f567 100644 (file)
@@ -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
                        {