copy & rename files to other folder - batch-file

I have some of log files formatted like this "name.log"
I would like to copy those from one folder to another folder like
xcopy /y "C:\Folder1" "D:\Folder2"
And i need to rename file with created date of original file (no copy file) so that the text file in Folder2 would be like "name yyyymmddhhmm.log" if some file has the same name (date of creation) it will be overwritten.
The code:
set Source=C:\Users\user1\Desktop\Folder1
set Dest=D:\Folder2
if not exist %Dest% md %Dest%
for /F %%a in ('dir /b "%Source%\*.txt"') do call :Sub %%a
goto :eof
:Sub
set "filename=%1"
for /F %%s in ("%Source%\%1") do if %%~zs==0 goto :eof
set "datepart="
FOR /F "tokens=1-5 delims=/-: " %%a IN ('dir /tc "%filename%" ^| findstr "%filename%"') DO (
IF "%%c" neq "" SET "datepart=%%c%%a%%b%%d%%e"
)
FOR /F %%a IN ("%filename%") DO (
set "NewName=%%~na %datepart%%%~xa"
)
xcopy /y "%Source%\%filename%" "%Dest%\%NewName%*"
GOTO :EOF
The problem is that If I don't put the .bat in the same folder that origin files (Folder1),the files aren't change name. For example, if it is out, the files change name with old name and one white space.
The command windows tell me that it doesn't find the file when it get the creation date.
If I put the script into folder1 it works well.
On the other hand, if I execute the script with "Task Scheduler" I have the same problem. The files are copied but without date of creation.
What do I need to solve this problem?

#ECHO OFF
SETLOCAL
set Source=C:\Users\user1\Desktop\Folder1
set Dest=D:\Folder2
set "Source=u:\sourcedir\t w o"
set "Dest=u:\destdir"
if not exist "%Dest%" md "%Dest%"
for /F "delims=" %%k in ('dir /b "%Source%\*.log"') do call :Sub "%%k"
goto :eof
:Sub
SET "newname=%~1"
for /F "delims=" %%s in ("%Source%\%~1") do (if %%~zs==0 goto :eof
FOR /F "tokens=1-5 delims=/-: " %%a IN ('dir /tc "%Source%\%~1" ^| findstr "%~1"') DO (
IF "%%c" neq "" SET "newname=%%~ns %%c%%a%%b%%d%%e%%~xs"
)
)
ECHO(xcopy /y "%Source%\%~1" "%Dest%\%NewName%"
GOTO :EOF
The required XCOPY commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(XCOPY to XCOPY to actually copy the files. Append >nul to suppress report messages (eg. 1 file copied)
This may seem quite a radical change, but actually it really isn't.
First issue is that I overrode your directory settings with directories to suit my system. The syntax SET "var=value" (where value may be empty) is used to ensure that any stray trailing spaces are NOT included in the value assigned. set /a can safely be used "quoteless".
Using quotes in the md command makes the procedure immune to "paths containing separators" - I test using spaces in paths and filenames because that appears to be a popular thing to do.
I changed the directory-scan metavariable from %%a to %%k to avoid confusion with the %%a in the subroutine. Your text says that you are starting with &.log files, but your filemask was *.txt so I changed it to *.log. Quoting the parameter delivered to :Sub means the procedure will receive the entire name of the file if it contains spaces.
Within the subroutine, it would appear that yowant no name-change if the %%c part from the dir/tc scan is empty. %~1 is the supplied filename minus the quotes.
The outer loop in %%s : I added delims= to cater for spaces in filenames and used %~1 in preference to %filename%
Within the %%s block, %%s refers to the file, so you can use %%s and its modified forms like %%~zs to refer to that file's characteristics - which unfortunately do not include create-date (%%~ts contains the last-update date - you may be able to use that in te following line rather than dir and findstr)
Then as #aschipfi suggested, include the source directory in the dir otherwise the dir takes place on the current directory.
FOR /F "tokens=1-5 delims=/-: " %%a IN ("%%~ts") DO (
should work for you if you can use last-update-date in place of create-date.
So - if %%c is not empty, set the new name to (the name part of the file in %%s)+space+the date string+(the extension in %%s)
And then do the xcopy - using the old name unless it was modified.

Related

Creating List of Folders from File Names

I have a folder containing many files named as such: JBMA_23456.docx, JMRI_21456.docx, CM_22554.docx, QUA_11224.docx. How do I create a sub-folder for each file bearing the same name as the file but without the .docx file extension? Additionally, I want to store the filename only as variables.
For example, I need to create a sub-folder named JBMA_23456 from the document
JBMA_23456.docx. Can anyone point me in teh right direction?
#echo off
for %%A in (*.docx) do if not exist "%%~nA" md "%%~nA"
This creates a folder with the same name as each .docx file.
View modifiers in for /? or in call /?. The n modifier is the name.
Path modifiers:
dpnx is drive, path, name and extension.
Here's an example batch file which attempts to perform the tasks as laid out in your question:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "BaseDir=C:\Users\Compo\Desktop\test"
Set "FileExt=.docx"
For /F "Delims==" %%A In ('Set var[ 2^>Nul') Do Set "%%A="
Set "i=0"
For /F "Delims=" %%A In ('Where "%BaseDir%":*%FileExt% 2^>Nul') Do (Set /A i+=1
Call Set "var[%%i%%]=%%~nA"
If Exist "%%~dpA%%~nA\" (Echo Sub-Folder %%~nA already exists in %BaseDir%
) Else (Set /P "=Creating sub-folder %%~nA in %BaseDir%"<Nul
MD "%%~dpA%%~nA">Nul 2>&1 && (Echo= was successful) || Echo= failed))
Set var[ 2>Nul
Pause
In order to use it, you would first ensure that the directory holding your files, (excluding any trailing backslash), is placed between the = and " on line 4, and the single file extension, (including the leading period, .), similarly on line 5.
It is not entirely clear what you are asking for...
Anyway, here is the code i made
echo off
chcp 65001
cls
for /f "usebackq delims=." %%0 in (`dir /b "*.docx"`) do (
set filename=%%0
md %filename%
)
cmd /k
It creates a new folder for every file. Feel free to ask if this was not what you expected

How to remove a prefix from multiple files?

I downloaded a lot of videos that are named like [site.com] filename.mp4 and I wanted to remove the prefix so that they are named like filename.mp4.
I tried a batch file with the following code:
ren "[site.com] *.mp4" "///////////*.mp4"
But the result was .com] filename.mp4 and can't rename anything beyond the dot, any ideas?
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f "tokens=1*delims=]" %%a IN (
'dir /b /a-d "%sourcedir%\*" '
) DO IF "%%b" neq "" (
FOR /f "tokens=*" %%h IN ("%%b") DO ECHO(REN "%sourcedir%\%%a]%%b" "%%h"
)
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
The required REN commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(REN to REN to actually rename the files.
Perform a directory scan of the source directory, in /b basic mode /a-d without directories and tokenise each filename found - the part before the first ] to %%a and the remainder to %%b.
If %%b is not empty (ie. did not contain ]) then do nothing, therwise use the default token set (which includes space) and tokens=0 to strip the leading spaces from %%b into %%h, then build the original filename and rename.
Use a for loop to split on the space in the name.
#echo off
:: Pass the file name in as an argument.
:: Split the full path into a directory and filename in case the folder has a space too
set "filepath=%~dp1"
set "filename=%~nx1"
:: Jump into the hosting directory, split the file name after the first space, and jump out
pushd %filepath%
for /f "tokens=1,*" %%A in ("%filename%") do ren "%filename%" "%%B"
popd
Just for completeness, a cmd.exe alternative:
For %A In ("*] *.*") Do #(Set "_=%A"&Call Ren "%A" "%_:*] =%")
Use parameter expansion with pattern replacement.
f='[site.com] filename.mp4'
mv "$f" "${f/\[site\.com\] /}"
Even Windows systems can execute a Bash.
http://www.mingw.org/wiki/msys
This is a for loop:
for f in *.mp4; then
mv "$f" "${f/\[site\.com\] /}"
done

copy and rename file with create date (Batch script)

I have some of log files formatted like this "name.log"
I would like to copy those from one folder to another folder like
xcopy /y "C:\Folder1" "D:\Folder2"
Adding I need to rename file with created date of original file (no copy file) so that the text file in Folder2 would be like "yyyymmddhhmm.log" if some file has the same name (date of creation) it will be overwritten.
I have a code with help of #Wes Larson but there is something wrong.
set Source=C:\Users\user1\Desktop\1
set Dest=C:\Users\user1\Desktop\2
if not exist %Dest% md %Dest%
for /F %%a in ('dir /b "%Source%\*.txt"') do call :Sub %%a
goto :eof
:Sub
set "filename=%1"
for /F %%s in ("%Source%\%1") do if %%~zs==0 goto :eof
set "datepart="
FOR /F "tokens=1-5 delims=/-: " %%a IN ('dir /tc "%filename%" ^| findstr "%filename%"') DO (
IF "%%c" neq "" SET "datepart=%%c%%a%%b%%d%%e"
)
FOR /F %%a IN ("%filename%") DO (
set "NewName=%%~na %datepart%%%~xa"
)
xcopy /y "%Source%\%filename%" "%Dest%\%NewName%*"
GOTO :EOF
The problem is that If I don't put the .bat in the same folder that origin files (Folder1),some files aren't change name. For example, if it is out some files change name with old name and one white space. The command windows tell me that it doesn't find the file when it get the creation date. It's very strange because some files are copied well.
What do I need to solve this problem?
Before we get to an answer: When troubleshooting/debugging batch scripts, don't use #echo off. It's great once you have it working the way you want, but comment it out when you need to see what your code is doing line by line. Also, you'll want to open a cmd window and run your script from a command line, so the window doesn't close as soon as your script finishes.
Now on to your code. This for loop is part of your problem:
FOR /f "tokens=1-3delims=/-:" %%a IN ('dir /tc "%filename%"') DO IF "%%c" neq "" SET "datepart=%%a-%%b-%%c"
Firstly, you haven't set %filename%, so this loop will fail. You should probably have a line in your :Sub like this:
set "filename=%1"
Now, assuming that %filename% is fixed, by the time this loop has finished, your %%a, %%b, and %%c variables have been set to the values in the last line of output from the command 'dir /tc "%filename%"', which is something like X Dir(s) XXX,XXX,XXX,XXX bytes free, and isn't the information you're looking for.
So, instead, you can tweak it a little so that you pipe the output of dir to findstr, looking for just the one, single line that you want to use, like this:
FOR /f "tokens=1-3delims=/-:" %%a IN ('dir /tc "%filename%" ^| findstr "%filename%"') DO (
IF "%%c" neq "" SET "datepart=%%a-%%b-%%c"
)
But then, you have another problem: your %datepart% looks like MM-DD-YYYY hh. This is because you changed your delims from the default (which includes spaces and tabs), to only the specified characters. Also, from your question, you want to also include hour and minute all formatted as "yyyymmddhhmm.log" , which means you'll need those next two tokens, too. Then your line becomes this:
FOR /f "tokens=1-5 delims=/-: " %%a IN ('dir /tc "%filename%" ^| findstr "%filename%"') DO (
IF "%%c" neq "" SET "datepart=%%c%%a%%b%%d%%e"
)
Next, your nested for loop is confusing, unnecessary, and causing problems:
FOR /f %%a IN ("%filename%") DO FOR /f %%d IN ("%datepart%") DO (
set NewName="%%~na %%d%%~xa
xcopy e/d/y "%Source%\%OrgName%" "%Dest%\%NewName%"
)
You already have the %datepart% variable, and you don't need to turn it into one of the for %%d variables to be able to reference it. So it becomes much simpler when you do it like this:
FOR /f %%a IN ("%filename%") DO (set "NewName=%%~na %datepart%%%~xa")
Also, because you run into delayed expansion issues, it's simpler to take the xcopy command out of the loop.
And once again, you have a variable %OrgName% that you never set. Fortunately, this is actually unnecessary as you already have the original file name captured as %filename%. So your overly complicated nested for loop becomes this:
FOR /f %%a IN ("%filename%") DO (
set "NewName=%%~na %datepart%%%~xa"
)
echo xcopy e/d/y "%Source%\%filename%" "%Dest%\%NewName%"

create folders based on string in file name

I need a batch file to create a process for a list of files in a directory.
The filename structure is, for example: 00000_AAA_132144_2012021.txt
I need the batch to:
1 - Create a folder name based on the numbers after the second underscore, as this is the only constant in the naming.
2 - Move the file into the new folder.
In the example of the above the batch would create a folder called 132144 and then move the file 00000_AAA_132144_2012021.txt into the folder
For a similar requirement I used the script Endoro created for me (below). Is it possible to modify this to meet my requirement?
#echo off &setlocal
for /f "delims=" %%i in ('dir /b /a-d *.PDF') do (
set "filename1=%%~i"
setlocal enabledelayedexpansion
set "folder1=!filename1:~11,6!"
mkdir "!folder1!" 2>nul
move "!filename1!" "!folder1!"
endlocal
)
If you know that the filenames will be the same length, you can do the following to get the numbers after the second underscore -
set filename=00000_AAA_132144_2012021.txt
set dirname=%filename:~10,6%
If the spacing may vary - you can do the following -
for /f "delims=_ tokens=3" %%a in ('echo %filename%') do set dirname=%%a
And yes, the script written for you seems to do essentially the same thing as what you're asking - I've edited it to do what you've asked -
#echo off
setlocal enabledelayedexpansion
for /f %%i in ('dir /b /a-d *.txt') do (
set "filename=%%~i"
for /f "delims=_ tokens=3" %%a in ('echo !filename!') do set folder=%%a
mkdir "!folder!" 2>nul
move "!filename!" "!folder!"
)
This will move all *.txt documents to a folder created based on the third section of the text files name. Note that this will cause problems if you have .txt documents in the directory that do not follow the same naming standard.
#ECHO OFF
SETLOCAL
SET "sourcedir=c:\sourcedir"
SET "destdir=c:\destdir"
FOR /f "delims=" %%a IN ('dir /b /a-d "%sourcedir%\*_*_*_*.txt" ') DO (
FOR /f "tokens=3delims=_" %%m IN ("%%a") DO (
ECHO MD "%destdir%\%%m"
ECHO MOVE "%sourcedir%\%%a" "%destdir%\%%m\"
)
)
GOTO :EOF
Endoro's routine selects .pdf files, you've specified .txt
Find filenames matching the mask, find the third _-separated token in the name, make that directory and then move the file.
The required commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO MD to MD to actually create the directories and change ECHO MOVE to MOVE to actually move the files.
Append 2>nul to suppress error messages (eg. when the directory already exists)
Append >nul to suppress report messages (eg. 1 file moved)

Batch: Rename multiple files using input string

I am trying to rename files after the user inputs a string they want to remove from the file name. This works fine except when I want to rename files that are in a different location than the script:
Here is what i have so far which works if I dont specific the file path (e.g. remove C:\DATABASE\*.* /s)
SET /P X=Type in the String that you want to remove and then press ENTER:
set deletestring=%X%
for /f "delims==" %%F in ('dir C:\DATABASE\*.* /s /b ^| find "%deletestring%"') do (
set oldfilename=%%F
set newfilename=!oldfilename:%deletestring%=!
Ren "!oldfilename!" "!newfilename!"
)
Thanks!
Use this instead. e.g.:
remove *.*
or
remove "relative path\*.*"
or
remove C:\DATABASE\*.*
or
remove "C:\My Database\2010-*.bak"
Meaning that a directory and file mask must be specified. Here's the remove.bat file:
#echo off
setlocal enabledelayedexpansion
set mask=%~1
set mask=!mask:%~dp1=!
if not exist "%~1" (
echo No files found
goto :eof
)
pushd "%~dp1"
SET /P X=Type in the String that you want to remove and then press ENTER:
set deletestring=%X%
for /f "delims==" %%F in ('dir "%mask%" /s /b ^| find "%deletestring%"') do (
set oldfilename=%%F
set newfilename=!oldfilename:%deletestring%=!
Ren "!oldfilename!" "!newfilename!"
)
Your primary problem you are running into is that the 1st argument to REN can accept full path info, but the 2nd can only contain the new name without path info. You can use the ~nx modifier to extract the name and extension from the full path reported by the FOR /F command.
Your FOR /F options are not reliable - it will break if the file name contains =. You want to set delims to nothing instead.
This problem is actually more complicated than it first looks. Your code will attempt to rename both files and directories. If you want to rename the directories then you must rename in reverse alpha order because the entire list is built before any thing is renamed. If you process in normal alpha order and rename a directory, then subsequent entries within that directory will not be found.
The FIND filter in the IN() clause is not necessary. Ideally your filter should only match the file or directory name, not the path. That is doable, but a bit tricky. I would simply skip the filtering in the IN() clause and do it in the DO clause.
A file or directory name can contain ! character. But the FOR variable expansion will be corrupted if it contains ! and delayed expansion is enabled. The problem can be avoided by toggling delayed expansion on and off within the loop.
It is possible for the entire name to be removed by the search and replace, but you cannot rename a file to nothing. So I added a test to ensure there is a name left.
setlocal disableDelayedExpansion
SET /P "X=Type in the String that you want to remove and then press ENTER:"
for /f "delims=" %%F in ('dir C:\DATABASE\* /s /b ^| sort /r') do (
set "old=%%F"
set "file=%%~nxF"
setlocal enableDelayedExpansion
set "new=!file:%X%=!"
if defined new if !new! neq !file! ren "!old!" "!new!"
endlocal
)
If you don't really want to rename directories then you need to add the /A-D option. I first thought you could use a FOR /R statement, but that could potentially cause the same file to be renamed twice. FOR /F buffers the entire result set before processing any files, but FOR /R does not.
setlocal disableDelayedExpansion
SET /P "X=Type in the String that you want to remove and then press ENTER:"
for /f "delims=" %%F in ('dir C:\DATABASE\* /s /b /a-d') do (
set "old=%%F"
set "file=%%~nxF"
setlocal enableDelayedExpansion
set "new=!file:%X%=!"
if defined new if !new! neq !file! ren "!old!" "!new!"
endlocal
)

Resources