Find, Copy and Rename in BATCH - batch-file

Good Morning!
Coming from another article, which i tried to adopt, but failed, i would like to ask my question in a separate post. I need to achieve two things:
Copy all files that contain a certain string in their filename from one directory to another, but only if that file does not already exists in that target directory. The filename could be something like EventLog_12345.txt and i would want to copy only the files where the filename contains EventLog.
In a set of files identify in every .txt file a certain string. This string indicates the line that contains the string i am looking for. I want to get to the end of this line and save the .txt file as a new .txt file with a new name based on the string i find at the end of this line. Example: My file is EventLog_12345.txt and somewhere in this file there is a line like this:
2018-06-22 08:21:19 0133 LET vVariable = 'h**ps://somedomain.com/test/1/2/4/jobs/joblog.XML'
The string indicating the line is vVariable.
The string i want to use within the new filename in this example is joblog.xml. The file should be stored as a new .txt file with the name: joblog_12345.txt. Note, that the length of the line can vary; so can the length of the domain string; also the names of the XMLs are different. The constant is that i always
want to have the name of the XML file which is always the last piece of the domain.
Adding info on efforts so far
Copy & Paste - this is actually working, but does not check whether a file already exists:
#echo off
for /f "delims=" %%a in (
'xcopy /l /e /y "\\myPath\*EventLog*.txt" "D:\Target\" ^|find "EventLog"'
) do copy "%%a" "D:\Target\"
For the identification of string and then SaveAs i dont really have anything. I was basically hoping i could somehow adjust the solution provided here: (Rename text files based on multiple strings in their contents)

For 1st
#echo off
Set "Target=D:\Target\"
for /f "delims=" %%A in (
'xcopy /l /e /y "\\myPath\*EventLog*.txt" "%Target%" '
) do if not exist "%Target%%%~nxA" copy "%%A" "%Target%"
For 2nd
process a list of files containing vVariable with findstr /I /M "vVariable" *_*.txt in %%A
Split the found name at the underscore %%B
search file to get the Line and exchange all / in the line to spaces to then
get the very last element in %%D
use %%~nD without extension to form the new name
:: Q:\Test\2018\05\22\SO_50982243.cmd
#Echo off & Setlocal EnableDelayedExpansion
For /f "delims=" %%A in ('findstr /I /M "vVariable" *_*.txt ') Do (
For /f "tokens=2delims=_" %%B in ("%%~nA") Do (
For /f "delims=" %%C in ('findstr /I "vVariable" ^<"%%A"') Do Set "Line=%%C"
Set "Line=!Line:/= !"
For %%D in (!Line!) Do Set "NewName=%%~nD_%%B%%~xA"
Echo Ren "%%~A" "!NewName!"
)
)
Sample output based on your information
> SO_50982243.cmd
Ren "EventLog_12345.txt" "joblog_12345.txt"
If the output looks OK remove the echo in front of ren to really rename.

Related

Can I use the variable name specified in the do syntax immediately? In batch file [duplicate]

This question already has an answer here:
Variables are not behaving as expected
(1 answer)
Closed 3 months ago.
I want to find file list PATH1
and overwrite it if there is a file with the same name on PATH2.
#echo off
SET PATH1="FIND_PATH"
SET PATH2="OVERWRITE_PATH"
for /f "delims=" %%A in ('dir /b %PATH1%') do (
dir /s /b /r %PATH2% | find /i "%%A" > list.txt
SET /p PATH3<=list.txt
move %PATH1%%%A %PATH3%
)
At line 7,
If possible, it would be nice to store it in a variable without going through list.txt in the middle.
I perform "ECHO %PATH3%" outside the for syntax, the last saved item is output.
but I perform "ECHO %PATH3%" inside the do syntax, Outputs an error.
how can I do.
thx.
Here's my analysis of your code:
for /f "delims=" %%A in ('dir /b %PATH1%') do (
rem %%A contains filename + extension of each file AND DIRECTORY in path1
dir /s /b /r %PATH2% | find /i "%%A" > list.txt
rem LIST.txt contains full pathnames of all filenames AND DIRECTORIES
rem where "%%A" forms part of the full pathname
SET /p PATH3<=list.txt
rem PATH3 contains the first line of list.txt
move %PATH1%%%A %PATH3%
rem move `path1%%A` (a file or directoryname - but without the `\` separator)
rem to the first (probably filename) found
)
Comment : first time in using batch for the last 40 years that I've ever seen the /r swich used in a dir statement...
So - we have to make some reasonable assumptions as to the intent of this code.
Tip: Use set "var=value" for setting string values - this avoids problems caused by trailing spaces. Don't assign " or a terminal backslash or Space. Build pathnames from the elements - counterintuitively, it is likely to make the process easier. If the syntax set var="value" is used, then the quotes become part of the value assigned.
#echo off
SET "PATH1=FIND_PATH"
SET "PATH2=OVERWRITE_PATH"
for /f "delims=" %%b in ('dir /b /a-d "%PATH1%"') do (
for /f "delims=" %%u in ('dir /s /b /a-d /r "%PATH2%\%%b" 2^>nul') do (
ECHO move "%PATH1%\%%A" "%%u"
)
)
[1] Change to better set syntax
[2] Prefer to avoid ADFNPSTXZ (in either case) as metavariables (loop-control variables) as ADFNPSTXZ are metavariable-modifiers which can lead to difficult-to-find bugs (See for/f from the prompt for documentation)
[3] Include /a-d to exclude directory names from dir lists
[4] Include %%b in the filemask for the inner for to search for that exact name only in the destination directory-tree
[5] The 2^>nul suppresses an error message should no files be found in the destination-tree matching the filename. The caret (^) is required to tell cmd that the > is part of the dir command, not the for
[6] Append the filename found (%%b) to the source directoryname with required separator
[7] %%u will contain the full pathnames of the matching files in the destination directory-tree
[8] The resultant command is merely echoed for verification. After verification, remove the echo keyword to actually execute the move.
Untested
Always verify against a test directory before applying to real data.
The effect would be to find all of the filenames in the source directory and move it over all matching filenames in the destination directory tree.
LOGICAL FLAW
a "move" command would move a file a.txt over the first a.txt in the destination-tree. Then the source file no longer exists (as it's been moved) so if a second a.txt is located in the destination-tree, then the move will fail.
Consider this further modification:
#echo off
SET "PATH1=FIND_PATH"
SET "PATH2=OVERWRITE_PATH"
for /f "delims=" %%b in ('dir /b /a-d "%PATH1%"') do (
set "moved="
for /f "delims=" %%u in ('dir /s /b /a-d /r "%PATH2%\%%b" 2^>nul') do (
set "moved=y"
ECHO COPY "%PATH1%\%%A" "%%u"
)
if defined moved (
ECHO del "%PATH1%\%%A"
) else (
ECHO "%PATH1%\%%A" - no matches in tree "%PATH2%" found
ECHO MOVE "%PATH1%\%%A" "%PATH2%"
)
)
This change sets moved to nothing for each source file found, then sets it to y if any matching filename is found n the destination tree.
If the file has been copied, then delete the source file, otherwise complain and move it to the destination-tree-root.

Renaming MM.DD.YY files to YY.MM.DD with .bat

I'm trying to make a .bat file which iterates through every file in the directory which the .bat file is in, and renames all the files which follow the naming convention of MM_DD_YY*.* to YY_MM_DD*.*.
For example, 05.20.16 MyFile.txt would become 16.05.20 MyFile.txt.
I've managed to iterate through the filenames, but I'm having trouble with making a substring of the beginning 8 characters and comparing them to the format of ##.##.##.
#echo off
setlocal EnableDelayedExpression
for /f %%i in ('dir /b') do (
set fn=%%i
:: Need to compare first 8 chars to ##.##.##
if %fn:~0,8%==??.??.?? echo FollowsFormat
)
Any help is appreciated!
Provided:
the date in the file name is always followed by a space.
You can use delimiters . and spaceto seperate date elements and remaining file name into for variables %%A - %%D and rearrange them in the desired order.
To better distinguish old from new format I suggest to change the delimiter (at least temporarily) to a - and extend the year to 4 digits.
#echo off & setlocal EnableDelayedExpression
for /f "tokens=1-3* delims=. " %%A in (
'dir /b /A-D "??.??.?? *.txt" ^| findstr "^[01][0-9]\.[0-3][0-9]\.[0-9][0-9].*"'
) do Echo Ren "%%A.%%B.%%C %%D" "20%%C-%%A-%%B %%D"
For security reason the batch only echoes what it would rename
until you remove the echo in front of ren if the output looks OK.

Using batch commands to create folders and copy filenames

I want to copy all files on a list to another location and create sub-folders in that location based on certain attributes of the filenames. In this case, the company names. All files are currently located in desktop\main.
For example, lets say the list has filenames like
From((Sales#JonesCompany.com))main.txt
From((AR#PeterIndustries.com))main.txt
From((AP#BaseCorporation.com))main.txt
The script should copy those files, make a directory like JonesCompany.com, and finally copy all respective filenames to that location.
The end result should be like
desktop\final_location\JonesCompany\
desktop\final_location\PeterIndustries\
desktop\final_location\BaseCorporation\
So far I have
for /f "delims=" %%i in (main.txt) do echo F|xcopy "C:\Users\Desktop\Main\%%i" MD %%i "C:\Users\Desktop\final_location\%%i" /i /z /y
Thanks in advance
I think this does what you want:
#ECHO OFF
SETLOCAL
set "basepath=C:\Users\Desktop\Main\"
set "filter=*.txt"
set "targetpath=C:\Users\Desktop\final_location\"
echo scanning %basepath%%filter%
for %%i in ("%basepath%%filter%") do (
for /F "tokens=1,2,3 delims=#)" %%a in ("%%i") do (
echo Creating Folder %%b...
mkdir %basepath%%%b\
echo copying file %%i to %targetpath%%%b\...
copy "%%i" %targetpath%%%b\
)
)
You can easily change the basepath, targetpath and filter variables as needed.
Explanation
The trickiest part is for /F "tokens=1,2,3 delims=#)" %%a in ("%%i") do (. %%i is a filename. Let's say it's From((Sales#JonesCompany.com))main.txt. This for statement will split the string at any instance of the delimiters # or ). This leaves us with the following array of strings:
%%a: "From((Sales"
%%b: "JonesCompany.com"
%%c: NULL (I think)
%%d: "main.txt"
Obviously, we want %%b so we use it as the new folder name. We then copy %%i, the original full path, to the new folder.
update removed a loop thanks to #Stephan pointing out something I didn't realize!

renaming files to a new name folder using batch script

Have tried to rename files in a folder with this script, but its seems not to work
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SET old=*.txt
SET new="c:\path to file that contains the listed names"
for /f "tokens=*" %%f in ('dir /b *.txt') do (
SET newname=%%f
SET newname=!newname:%old%=%new%!
move "%%f" "!newname!"
)
what am trying to achieve is my script should pick set of listed names in a file and rename each file in the specified folder accordingly
test this script
#echo off
set prefix=new
setlocal EnableDelayedExpansion
for /f "delims=" %%a in ('dir *.txt /b') do (
set name=%%~Na
set newName=%prefix%!name:~0,1!X!name:~1,2!!name:~3!
ren "%%a" "!newName!%%~Xa")
First you said you want to rename each file "accordingly" (accordingly to what?), and later in a comment you said you try to rename files "with a set of listed names in a file". This point cause several additional questions: Have this file one name in each line? Must the first file listed by dir /b *.txt match the first name listed in the file, and so on? Any other option? (Why do you use a move command to do a "rename"?).
Because the objective is not clear, we can not said if your code is right or not. However, this is what your code does. Suppose the first file is "firstFile.txt"; then this section:
SET newname=%%f
SET newname=!newname:%old%=%new%!
move "%%f" "!newname!"
is executed this way:
SET newname=firstFile.txt
SET newname=!newname:*.txt="c:\path to file that contains the listed names"!
Previous line replace from the beginning of newname until ".txt" (that is, the entire value) by "c:\path to file that contains the listed names", so the next line is executed this way:
move "firstFile.txt" ""c:\path to file that contains the listed names""
that correctly should move the file into the given path even if it contains a pair of quotes at each side.
If the objective would be "Rename files in a folder to the names listed in a text file one-by-one", then you must do a merge between two lists: the file list created by dir /b *.txt and the name list stored in the file.
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SET old=*.txt
SET new="c:\path to file that contains the listed names"
< %new% (for /f "tokens=*" %%f in ('dir /b %old%') do (
ren Read the next name from the redirected input file
SET /P newname=
ren "%%f" "!newname!"
))
If this is not what you want, please clearly describe the desired process...

How to set variable in batchfile

I want to move files according to folder names.
1.Some folder names have been written in b2.txt. In my b2.txt, every line contains one or two or three words, connected by space or "-". Like this:
transfer print
anti-foamer
insect
fibre reinforced plastic
2.My files are in "E:\JP-XIN\".
3.In E disk, there must exist one (only one) folder name consisting of one line in b2.txt.
My question is how to set every line in b2.txt exactly as variable.
In the following code, "%%k" is the file name gotten by searching, "%%l" is the path to the folder gotten by searching. The code did not work correctly.
#echo off
setlocal ENABLEDELAYEDEXPANSION
for /f "delims=" %%a in (b2.txt) do (
set VAR=%%a
for /f "delims=" %%k in ('dir /s/b/a-d E:\JP-XIN\*.pdf E:\JP-XIN\*.txt ^| findstr /i /c:"!VAR!"') do (
for /f "delims=" %%l in ('dir /s/b/a:d-h E:\ ^| findstr /i /c:"!VAR!"') do (
if not "%%l"=="" move "%%k" "%%~fsl"
)))
pause
I had some time to spent so I worked overtime in how to solve what I think your problem is.
If your requirements are these:
The b2.txt file contains several folder names, with possible spaces.
In E:\ there is one folder that is contained in b2.txt.
In E:\JP-XIN\ there are several *.pdf and *.txt files.
and you want to:
Locate the folder that is contained in b2.txt, and
Move to it the *.pdf and *.txt files that have the same name of the folder
then the Batch file below solve your problem:
#echo off
for /f "delims=" %%a in (b2.txt) do (
if exist "E:\%%a" (
move "E:\JP-XIN\%%a.pdf" "E:\%%a"
move "E:\JP-XIN\%%a.txt" "E:\%%a"
)
)
If the .pdf and .txt are the only files with that name, then the two move commands may be joined in just one:
move "E:\JP-XIN\%%a.*" "E:\%%a"
If this is not your problem then, please, tell us what your problem is!
You need to use tokens=* to return the entire line as a single variable.
for /f "tokens=* delims=" %%a in (b2.txt) do (
You can also write things like tokens=1,2* which makes the first variable token 1, the second variable token 2, and the third variable the rest of the line. So the text:
Several words on a line.
Would split to:
%%a = Several
%%b = words
%%c = on a line.

Resources