In native Windows, the COPY command will display the names of the files as they are copied. Wine should do the same. This change enables that.
-- v16: cmd: COPY should output file names as they are copied. cmd: Allow '+' as delimiter for tab-completion, e.g. 'copy file+file2'.
From: Joe Souza jsouza@yahoo.com
--- programs/cmd/tests/test_builtins.cmd | 79 ++++++++++++++++++------ programs/cmd/tests/test_builtins.cmd.exp | 42 +++++++++++++ 2 files changed, 102 insertions(+), 19 deletions(-)
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd index 58d78194380..8ae733681eb 100644 --- a/programs/cmd/tests/test_builtins.cmd +++ b/programs/cmd/tests/test_builtins.cmd @@ -3416,6 +3416,30 @@ shift if not "%1"=="" goto :CheckNotExist goto :eof
+:CheckOutputExist +find /i "%1" test1.txt >nul 2>&1 +if errorlevel 0 ( + echo Passed: Found expected %1 in COPY output +) else ( + echo Failed: Did not find expected %1 in COPY output +) +shift +if not "%1"=="" goto :CheckOutputExist +del /q test1.txt >nul 2>&1 +goto :eof + +:CheckOutputNotExist +find /i "%1" test1.txt >nul 2>&1 +if errorlevel 1 ( + echo Passed: Did not find %1 in COPY output +) else ( + echo Failed: Unexpectedly found %1 in COPY output +) +shift +if not "%1"=="" goto :CheckOutputNotExist +del /q test1.txt >nul 2>&1 +goto :eof + rem Note: No way to check file size on NT4 so skip the test :CheckFileSize if not exist "%1" ( @@ -3444,28 +3468,33 @@ rem ----------------------- rem Simple single file copy rem ----------------------- rem Simple single file copy, normally used syntax -copy file1 dummy.file >nul 2>&1 +copy file1 dummy.file >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputNotExist file1 call :CheckExist dummy.file
rem Simple single file copy, destination supplied as two forms of directory -copy file1 dir1 >nul 2>&1 +copy file1 dir1 >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputNotExist file1 call :CheckExist dir1\file1
-copy file1 dir1\ >nul 2>&1 +copy file1 dir1\ >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputNotExist file1 call :CheckExist dir1\file1
rem Simple single file copy, destination supplied as fully qualified destination -copy file1 dir1\file99 >nul 2>&1 +copy file1 dir1\file99 >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputNotExist file1 call :CheckExist dir1\file99
rem Simple single file copy, destination not supplied cd dir1 -copy ..\file1 >nul 2>&1 +copy ..\file1 >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputNotExist file1 call :CheckExist file1 cd ..
@@ -3477,19 +3506,22 @@ call :CheckNotExist dir2 dir2\file1 rem ----------------------- rem Wildcarded copy rem ----------------------- -rem Simple single file copy, destination supplied as two forms of directory -copy file? dir1 >nul 2>&1 +rem Simple wildcarded file copy, destination supplied as two forms of directory +copy file? dir1 >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputExist file1 file2 file3 call :CheckExist dir1\file1 dir1\file2 dir1\file3
-copy file* dir1\ >nul 2>&1 +copy file* dir1\ >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputExist file1 file2 file3 call :CheckExist dir1\file1 dir1\file2 dir1\file3
-rem Simple single file copy, destination not supplied +rem Simple wildcarded file copy, destination not supplied cd dir1 -copy ..\file*.* >nul 2>&1 +copy ..\file*.* >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputExist file1 file2 file3 call :CheckExist file1 file2 file3 cd ..
@@ -3502,51 +3534,60 @@ rem ------------------------------------------------ rem Confirm overwrite works (cannot test prompting!) rem ------------------------------------------------ copy file1 testfile >nul 2>&1 -copy /y file2 testfile >nul 2>&1 +copy /y file2 testfile >test1.txt 2>&1 +call :CheckOutputNotExist file2 call :CheckExist testfile
rem ------------------------------------------------ rem Test concatenation rem ------------------------------------------------ rem simple case, no wildcards -copy file1+file2 testfile >nul 2>&1 +copy file1+file2 testfile >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputExist file1 file2 call :CheckExist testfile
rem simple case, wildcards, no concatenation -copy file* testfile >nul 2>&1 +copy file* testfile >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputExist file1 file2 file3 call :CheckExist testfile
rem simple case, wildcards, and concatenation echo ddddd > fred -copy file*+fred testfile >nul 2>&1 +copy file*+fred testfile >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputExist file1 file2 file3 fred call :CheckExist testfile
rem simple case, wildcards, and concatenation -copy fred+file* testfile >nul 2>&1 +copy fred+file* testfile >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputExist fred file1 file2 file3 call :CheckExist testfile
rem Calculate destination name -copy fred+file* dir1 >nul 2>&1 +copy fred+file* dir1 >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputExist fred file1 file2 file3 call :CheckExist dir1\fred
rem Calculate destination name -copy fred+file* dir1\ >nul 2>&1 +copy fred+file* dir1\ >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputExist fred file1 file2 file3 call :CheckExist dir1\fred
rem Calculate destination name (none supplied) cd dir1 -copy ..\fred+..\file* >nul 2>&1 +copy ..\fred+..\file* >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputExist fred file1 file2 file3 call :CheckExist fred
-copy ..\fr*+..\file1 >nul 2>&1 +copy ..\fr*+..\file1 >test1.txt 2>&1 if errorlevel 1 echo Incorrect errorlevel +call :CheckOutputExist fred file1 call :CheckExist fred cd ..
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index ff6f944cffb..95feb67602b 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -1936,19 +1936,33 @@ file correctly deleted --- a batch file can alter itself bar ---------- Testing copy +Passed: Did not find file1 in COPY output Passed: Found expected dummy.file +Passed: Did not find file1 in COPY output Passed: Found expected dir1\file1 +Passed: Did not find file1 in COPY output Passed: Found expected dir1\file1 +Passed: Did not find file1 in COPY output Passed: Found expected dir1\file99 +Passed: Did not find file1 in COPY output Passed: Found expected file1 Passed: Did not find dir2 Passed: Did not find dir2\file1 +Passed: Found expected file1 in COPY output +Passed: Found expected file2 in COPY output +Passed: Found expected file3 in COPY output Passed: Found expected dir1\file1 Passed: Found expected dir1\file2 Passed: Found expected dir1\file3 +Passed: Found expected file1 in COPY output +Passed: Found expected file2 in COPY output +Passed: Found expected file3 in COPY output Passed: Found expected dir1\file1 Passed: Found expected dir1\file2 Passed: Found expected dir1\file3 +Passed: Found expected file1 in COPY output +Passed: Found expected file2 in COPY output +Passed: Found expected file3 in COPY output Passed: Found expected file1 Passed: Found expected file2 Passed: Found expected file3 @@ -1956,14 +1970,42 @@ Passed: Did not find dir2 Passed: Did not find dir2\file1 Passed: Did not find dir2\file2 Passed: Did not find dir2\file3 +Passed: Did not find file2 in COPY output Passed: Found expected testfile +Passed: Found expected file1 in COPY output +Passed: Found expected file2 in COPY output Passed: Found expected testfile +Passed: Found expected file1 in COPY output +Passed: Found expected file2 in COPY output +Passed: Found expected file3 in COPY output Passed: Found expected testfile +Passed: Found expected file1 in COPY output +Passed: Found expected file2 in COPY output +Passed: Found expected file3 in COPY output +Passed: Found expected fred in COPY output Passed: Found expected testfile +Passed: Found expected fred in COPY output +Passed: Found expected file1 in COPY output +Passed: Found expected file2 in COPY output +Passed: Found expected file3 in COPY output Passed: Found expected testfile +Passed: Found expected fred in COPY output +Passed: Found expected file1 in COPY output +Passed: Found expected file2 in COPY output +Passed: Found expected file3 in COPY output Passed: Found expected dir1\fred +Passed: Found expected fred in COPY output +Passed: Found expected file1 in COPY output +Passed: Found expected file2 in COPY output +Passed: Found expected file3 in COPY output Passed: Found expected dir1\fred +Passed: Found expected fred in COPY output +Passed: Found expected file1 in COPY output +Passed: Found expected file2 in COPY output +Passed: Found expected file3 in COPY output Passed: Found expected fred +Passed: Found expected fred in COPY output +Passed: Found expected file1 in COPY output Passed: Found expected fred Passed: file size check on file1 [5]@or_broken@Skipping file size check on NT4 Passed: file size check on file2 [8]@or_broken@Skipping file size check on NT4
From: Joe Souza jsouza@yahoo.com
--- programs/cmd/wcmdmain.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index e9c5be4ceb3..c178c2a5cb9 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -138,7 +138,7 @@ static void build_search_string(WCHAR *inputBuffer, int len, SEARCH_CONTEXT *sc) * Otherwise, parse the buffer to find the last parameter in the buffer, * where tab was pressed. */ - if (len && inputBuffer[len-1] == L' ') { + if (len && (inputBuffer[len-1] == L' ' || inputBuffer[len-1] == L'+')) { cc = len; } else { /* Handle spaces in directory names. Need to quote paths if they contain spaces. @@ -150,7 +150,8 @@ static void build_search_string(WCHAR *inputBuffer, int len, SEARCH_CONTEXT *sc) if (stripped_copy) { wcsncpy_s(last_stripped_copy, ARRAY_SIZE(last_stripped_copy), stripped_copy, _TRUNCATE); } - stripped_copy = WCMD_parameter(inputBuffer, nn++, ¶m, FALSE, FALSE); + /* Delimiters here are the same as specified in WCMD_parameter, but with '+' added. */ + stripped_copy = WCMD_parameter_with_delims(inputBuffer, nn++, ¶m, FALSE, FALSE, L" \t,=;+"); } while (param);
if (last_param) { @@ -189,11 +190,11 @@ static void find_insert_pos(const WCHAR *inputBuffer, int len, SEARCH_CONTEXT *s /* Handle paths here. Find last '\'. * If '\' isn't found then insert pos is the same as search pos. */ - while (cc > sc->search_pos && inputBuffer[cc] != L'\') { + while (cc > sc->search_pos && inputBuffer[cc] != L'+' && inputBuffer[cc] != L'\') { cc--; }
- if (inputBuffer[cc] == L'"' || inputBuffer[cc] == L'\') { + if (inputBuffer[cc] == L'"' || inputBuffer[cc] == L'+' || inputBuffer[cc] == L'\') { cc++; }
From: Joe Souza jsouza@yahoo.com
--- programs/cmd/builtins.c | 29 +++++++++++++++++++++++++++-- programs/cmd/cmd.rc | 1 + programs/cmd/wcmd.h | 1 + 3 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index b78ae9d293b..c2379598976 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -656,6 +656,7 @@ RETURN_CODE WCMD_copy(WCHAR * args) WCHAR copycmd[4]; DWORD len; BOOL dstisdevice = FALSE; + unsigned numcopied = 0;
typedef struct _COPY_FILES { @@ -954,6 +955,8 @@ RETURN_CODE WCMD_copy(WCHAR * args) WCHAR *filenamepart; DWORD attributes; BOOL srcisdevice = FALSE; + BOOL havewildcards = FALSE; + BOOL displaynames = anyconcats; /* Display names if we are concatenating. */
/* If it was not explicit, we now know whether we are concatenating or not and hence whether to copy as binary or ascii */ @@ -965,6 +968,13 @@ RETURN_CODE WCMD_copy(WCHAR * args) return errorlevel = ERROR_INVALID_FUNCTION; WINE_TRACE("Full src name is '%s'\n", wine_dbgstr_w(srcpath));
+ havewildcards = wcspbrk(srcpath, L"*?") ? TRUE : FALSE; + /* If we are not already displaying file names due to concatenation, then display them + if using wildards. */ + if (!displaynames) { + displaynames = havewildcards; + } + /* If parameter is a directory, ensure it ends in * */ attributes = GetFileAttributesW(srcpath); if (ends_with_backslash( srcpath )) { @@ -972,17 +982,19 @@ RETURN_CODE WCMD_copy(WCHAR * args) /* We need to know where the filename part starts, so append * and recalculate the full resulting path */ lstrcatW(thiscopy->name, L"*"); + displaynames = TRUE; if (!WCMD_get_fullpath(thiscopy->name, ARRAY_SIZE(srcpath), srcpath, &filenamepart)) return errorlevel = ERROR_INVALID_FUNCTION; WINE_TRACE("Directory, so full name is now '%s'\n", wine_dbgstr_w(srcpath));
- } else if ((wcspbrk(srcpath, L"*?") == NULL) && + } else if (!havewildcards && (attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
/* We need to know where the filename part starts, so append * and recalculate the full resulting path */ lstrcatW(thiscopy->name, L"\*"); + displaynames = TRUE; if (!WCMD_get_fullpath(thiscopy->name, ARRAY_SIZE(srcpath), srcpath, &filenamepart)) return errorlevel = ERROR_INVALID_FUNCTION; WINE_TRACE("Directory, so full name is now '%s'\n", wine_dbgstr_w(srcpath)); @@ -1064,6 +1076,10 @@ RETURN_CODE WCMD_copy(WCHAR * args)
/* Do the copy as appropriate */ if (overwrite) { + if (displaynames) { + WCMD_output_asis(srcpath); + WCMD_output_asis(L"\r\n"); + } if (anyconcats && WCMD_IsSameFile(srcpath, outname)) { /* behavior is as Unix 'touch' (change last-written time only) */ HANDLE file = CreateFileW(srcpath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, @@ -1097,7 +1113,12 @@ RETURN_CODE WCMD_copy(WCHAR * args) return_code = ERROR_INVALID_FUNCTION; } else { WINE_TRACE("Copied successfully\n"); - if (anyconcats) writtenoneconcat = TRUE; + if (anyconcats) { + writtenoneconcat = TRUE; + numcopied = 1; + } else { + numcopied++; + }
/* Append EOF if ascii destination and we are not going to add more onto the end Note: Testing shows windows has an optimization whereas if you have a binary @@ -1135,6 +1156,10 @@ RETURN_CODE WCMD_copy(WCHAR * args) } }
+ if (numcopied) { + WCMD_output(WCMD_LoadMessage(WCMD_NUMCOPIED), numcopied); + } + /* Exit out of the routine, freeing any remaining allocated memory */ exitreturn:
diff --git a/programs/cmd/cmd.rc b/programs/cmd/cmd.rc index 90091090e11..29d105fa7a2 100644 --- a/programs/cmd/cmd.rc +++ b/programs/cmd/cmd.rc @@ -406,4 +406,5 @@ Enter HELP <command> for further information on any of the above commands.\n" WCMD_BADTOKEN, "Syntax error: unexpected %1\n" WCMD_ENDOFLINE, "End of line" WCMD_ENDOFFILE, "End of file" + WCMD_NUMCOPIED, "%t%1!u! file(s) copied\n" } diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index 4c85d7ad8cb..2731743c27a 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -454,3 +454,4 @@ extern WCHAR version_string[]; #define WCMD_BADTOKEN 1047 #define WCMD_ENDOFLINE 1048 #define WCMD_ENDOFFILE 1049 +#define WCMD_NUMCOPIED 1050