Fixed obvious typos.
[reactos.git] / rosapps / cmd / ren.c
1 /*
2 * REN.C - rename internal command.
3 *
4 *
5 * History:
6 *
7 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
8 * added config.h include
9 *
10 * 18-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>
11 * Added support for quoted long file names with spaces.
12 *
13 * 20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>
14 * Unicode and redirection safe!
15 *
16 * 17-Oct-2001 (Eric Kohl <ekohl@rz.online.de>
17 * Implemented basic rename code.
18 */
19
20 #include "config.h"
21
22 #ifdef INCLUDE_CMD_RENAME
23
24 #include <windows.h>
25 #include <tchar.h>
26 #include <string.h>
27 #include <ctype.h>
28
29 #include "cmd.h"
30 #include "batch.h"
31
32 enum
33 {
34 REN_ATTRIBUTES = 0x001, /* /A : not implemented */
35 REN_ERROR = 0x002, /* /E */
36 REN_NOTHING = 0x004, /* /N */
37 REN_PROMPT = 0x008, /* /P : not implemented */
38 REN_QUIET = 0x010, /* /Q */
39 REN_SUBDIR = 0x020, /* /S */
40 REN_TOTAL = 0x040, /* /T */
41 };
42
43
44 /*
45 * file rename internal command.
46 *
47 */
48 INT cmd_rename (LPTSTR cmd, LPTSTR param)
49 {
50 LPTSTR *arg = NULL;
51 INT args = 0;
52 INT nEvalArgs = 0; /* nunber of evaluated arguments */
53 DWORD dwFlags = 0;
54 DWORD dwFiles = 0; /* number of renamedd files */
55 INT i;
56 LPTSTR srcPattern = NULL;
57 LPTSTR dstPattern = NULL;
58 TCHAR dstFile[MAX_PATH];
59 BOOL bDstWildcard = FALSE;
60
61 LPTSTR p,q,r;
62
63 HANDLE hFile;
64 WIN32_FIND_DATA f;
65
66 if (!_tcsncmp(param, _T("/?"), 2))
67 {
68 ConOutPuts(_T("Renames a file/directory or files/directories.\n"
69 "\n"
70 "RENAME [/E /N /P /Q /S /T] old_name ... new_name\n"
71 "REN [/E /N /P /Q /S /T] old_name ... new_name\n"
72 "\n"
73 " /E No eror messages.\n"
74 " /N Nothing.\n"
75 " /P Prompts for confirmation before renaming each file.\n"
76 " (Not implemented yet!)\n"
77 " /Q Quiet.\n"
78 " /S Rename subdirectories.\n"
79 " /T Display total number of renamed files.\n"
80 "\n"
81 "Note that you cannot specify a new drive or path for your destination. Use\n"
82 "the MOVE command for that purpose."));
83 return(0);
84 }
85
86 /* split the argument list */
87 arg = split(param, &args);
88
89 if (args < 2)
90 {
91 if (!(dwFlags & REN_ERROR))
92 error_req_param_missing();
93 freep(arg);
94 return(1);
95 }
96
97 /* read options */
98 for (i = 0; i < args; i++)
99 {
100 if (*arg[i] == _T('/'))
101 {
102 if (_tcslen(arg[i]) >= 2)
103 {
104 switch (_totupper(arg[i][1]))
105 {
106 case _T('E'):
107 dwFlags |= REN_ERROR;
108 break;
109
110 case _T('N'):
111 dwFlags |= REN_NOTHING;
112 break;
113
114 case _T('P'):
115 dwFlags |= REN_PROMPT;
116 break;
117
118 case _T('Q'):
119 dwFlags |= REN_QUIET;
120 break;
121
122 case _T('S'):
123 dwFlags |= REN_SUBDIR;
124 break;
125
126 case _T('T'):
127 dwFlags |= REN_TOTAL;
128 break;
129 }
130 }
131 nEvalArgs++;
132 }
133 }
134
135 /* keep quiet within batch files */
136 if (bc != NULL)
137 dwFlags |= REN_QUIET;
138
139 /* there are only options on the command line --> error!!! */
140 if (args < nEvalArgs + 2)
141 {
142 if (!(dwFlags & REN_ERROR))
143 error_req_param_missing();
144 freep(arg);
145 return(1);
146 }
147
148 /* get destination pattern */
149 for (i = 0; i < args; i++)
150 {
151 if (*arg[i] == _T('/'))
152 continue;
153 dstPattern = arg[i];
154 }
155
156 if (_tcschr(dstPattern, _T('*')) || _tcschr(dstPattern, _T('?')))
157 bDstWildcard = TRUE;
158
159 /* enumerate source patterns */
160 for (i = 0; i < args; i++)
161 {
162 if (*arg[i] == _T('/') || arg[i] == dstPattern)
163 continue;
164
165 srcPattern = arg[i];
166
167 #ifdef _DEBUG
168 ConErrPrintf(_T("\n\nSourcePattern: %s\n"), srcPattern);
169 ConErrPrintf(_T("DestinationPattern: %s\n"), dstPattern);
170 #endif
171
172 hFile = FindFirstFile(srcPattern, &f);
173 if (hFile == INVALID_HANDLE_VALUE)
174 {
175 if (!(dwFlags & REN_ERROR))
176 error_file_not_found();
177 continue;
178 }
179
180 do
181 {
182 /* ignore "." and ".." */
183 if (!_tcscmp (f.cFileName, _T(".")) ||
184 !_tcscmp (f.cFileName, _T("..")))
185 continue;
186
187 /* do not rename hidden or system files */
188 if (f.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))
189 continue;
190
191 /* do not rename directories when the destination pattern contains
192 * wildcards, unless option /S is used */
193 if ((f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
194 && bDstWildcard
195 && !(dwFlags & REN_SUBDIR))
196 continue;
197
198 #ifdef _DEBUG
199 ConErrPrintf(_T("Found source name: %s\n"), f.cFileName);
200 #endif
201
202 /* build destination file name */
203 p = f.cFileName;
204 q = dstPattern;
205 r = dstFile;
206 while(*q != 0)
207 {
208 if (*q == '*')
209 {
210 q++;
211 while (*p != 0 && *p != *q)
212 {
213 *r = *p;
214 p++;
215 r++;
216 }
217 }
218 else if (*q == '?')
219 {
220 q++;
221 if (*p != 0)
222 {
223 *r = *p;
224 p++;
225 r++;
226 }
227 }
228 else
229 {
230 *r = *q;
231 if (*p != 0)
232 p++;
233 q++;
234 r++;
235 }
236 }
237 *r = 0;
238
239 #ifdef _DEBUG
240 ConErrPrintf(_T("DestinationFile: %s\n"), dstFile);
241 #endif
242
243 if (!(dwFlags & REN_QUIET) && !(dwFlags & REN_TOTAL))
244 ConOutPrintf(_T("%s -> %s\n"), f.cFileName, dstFile);
245
246 /* rename the file */
247 if (!(dwFlags & REN_NOTHING))
248 {
249 if (MoveFile(f.cFileName, dstFile))
250 {
251 dwFiles++;
252 }
253 else
254 {
255 if (!(dwFlags & REN_ERROR))
256 ConErrPrintf(_T("MoveFile() failed. Error: %lu\n"), GetLastError());
257 }
258 }
259 }
260 while (FindNextFile(hFile, &f));
261 FindClose(hFile);
262 }
263
264 if (!(dwFlags & REN_QUIET))
265 {
266 if (dwFiles == 1)
267 ConOutPrintf(_T(" %lu file renamed\n"),
268 dwFiles);
269 else
270 ConOutPrintf(_T(" %lu files renamed\n"),
271 dwFiles);
272 }
273
274 freep(arg);
275
276 return(0);
277 }
278
279 #endif
280
281 /* EOF */