Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I am all new to batch files and DOS, but I hope you can help me anyway.

I need to copy files of a specific file type that are now in separate subdirectories, one such file per directory(but more files with different file types). They all have the same name, so when copying to a new folder the last file to be copied gets replaced by the following file when using the command described in this question: Copy files with certain extensions from multiple directories into one directory.

Would it be possible to first change the file names to the names of their respective directory and then use the command in the example? Or even better, change the name of the new copy of the file before putting it in the new directory, or after copying it there but before copying the following file?

share|improve this question

2 Answers 2

up vote 1 down vote accepted

Ok, here's one. You might want to consider using something more flexible than a batch file; a simple C++ program would have been much easier. Batch does not play nice with the string manipulation necessary to extract the directory name.

@ECHO OFF

SETLOCAL EnableDelayedExpansion

SET _destination=%~1
SHIFT

SET _source=%~1
SHIFT

SET _cmdstring=dir /b /s

:LoopGetExt
    SET _cmdstring=%_cmdstring% "%_source%\*%~1"
    SHIFT
    IF NOT "%~1"=="" GOTO LoopGetExt
::End LoopGetExt

FOR /F "tokens=*" %%i IN ('%_cmdstring%') DO (
        SET _fullpath=%%i
        SET _splitpath=!_fullpath:\=^

!
        SET _filename=%%~ni%%~xi
        FOR /F "tokens=*" %%j IN ("!_splitpath!") DO (
            IF NOT "%%j"=="!_filename!" SET _dirname=%%j
        )

        ECHO "%%i" =^> "%_destination%\!_dirname!_!_filename!"
        COPY "%%i" "%_destination%\!_dirname!_!_filename!"
)

ENDLOCAL

At the moment nothing has been hardcoded: to use it, do this.

copyfiles.bat <destination> <source> <ext> [ext]

e.g.

copyfiles.bat "C:\Dest" "C:\Source" .txt .xml .csv .log

EDIT (as per request in first comment)

::copyfiles.bat <destination> <source> <ext> [ext]
::e.g.
::copyfiles.bat "C:\Dest" "C:\Source" .txt .xml .csv .log

@ECHO OFF

SETLOCAL EnableDelayedExpansion

SET _destination=%~1
SHIFT

SET _source=%~1
SHIFT

SET _cmdstring=dir /b /s

:LoopGetExt
    SET _cmdstring=%_cmdstring% "%_source%\*%~1"
    SHIFT
    IF NOT "%~1"=="" GOTO LoopGetExt
::End LoopGetExt

FOR /F "tokens=*" %%i IN ('%_cmdstring%') DO (
        SET _fullpath=%%i
        SET _splitpath=!_fullpath:\=^

!
        SET _filename=%%~ni
        FOR /F "tokens=1 delims=. " %%j IN ("!_splitpath!") DO (
            IF NOT "%%j"=="!_filename!" SET _dirname=%%j
        )

        ECHO "%%i" =^> "%_destination%\!_dirname!%%~xi"
        COPY "%%i" "%_destination%\!_dirname!%%~xi"
)

ENDLOCAL
share|improve this answer
    
How do I change your batch file to not include the original file name, just the directory name without filetype, since all files have the same name? I would also like to remove the last part of the directory name. That is: directory "DirectoryName.d" and file name "FileName.fileType" becomes "DirectoryName.d_FileName.newFileType". What I want is "DirectoryName.newFileType". –  Joel Feb 20 '12 at 10:04
    
See the edit. It won't work if you have more than one . in the directory name, though, since it cuts off at the first .: DirectoryName.d.e becomes DirectoryName. –  Bob Feb 20 '12 at 11:03
    
Running the new edit gives just the FileName.newFileType as a name, not including the directory name, and since all files has the same name they are overwriting each other... –  Joel Feb 20 '12 at 12:40
    
Sorry, it's fixed now (but more than one . in the filename.ext will also break it) –  Bob Feb 20 '12 at 23:03

Based on the linked sample I have extended the code so that the file name will be changed to an increasing number, so that all xml files are copied to X:\destination using the old filename (inserted by %%~nxf) plus an increasing number.

@Echo Off
SET /A counter=1
for /R "X:\source" %%f in (*.xml) do (
    copy "%%f" "X:\destination\%%~nxf_!counter!.xml"
    SET /A counter=!counter!+1
    echo !counter!
)

Note that you can not simply execute this batch file. Because of the counter variable used in the for loop "delayed variable expanding" has to be enabled.

Therefore if you save the script above as mycopy.cmd you can start it as follows:

cmd.exe /v:on /c "mycopy.cmd"
share|improve this answer
    
It works, but the names of respective directory from where the files were copied are important for me in the following analysis of the files. Does someone know how to add them to the files? I was thinking of saving them all in a text or csv file and adding them afterwards, but guess there must be an easier solution? –  Joel Feb 17 '12 at 9:05
    
@Joel: See my updated answer. It now includes the old filename. –  Robert Feb 17 '12 at 11:54
    
Just saying, the proper way to do delayed variable expanding within a batch file is to use SETLOCAL EnableDelayedExpansion. –  Bob Feb 17 '12 at 13:48

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.