0

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?

2 Answers 2

1

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
4
  • 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, 2012 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, 2012 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, 2012 at 12:40
  • Sorry, it's fixed now (but more than one . in the filename.ext will also break it)
    – Bob
    Feb 20, 2012 at 23:03
1

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"
3
  • 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, 2012 at 9:05
  • @Joel: See my updated answer. It now includes the old filename.
    – Robert
    Feb 17, 2012 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, 2012 at 13:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .