I am trying to come up with a batch file to copy files based on their names.
The filenames are in form aaa_xx-XX-ccc.txt where aaa and ccc do not matter (variable length), but xx are 2 character codes. I would like to copy the files into their respective xx folders and these folders would also be created by the script.
Here I found something that almost suit my needs:
Batch file to copy files based on characters in filename
#echo off
setlocal enableextensions enabledelayedexpansion
for %%x in (*.txt) do (
set "filename=%%x"
set "folder=!filename:~1,2!"
if not exist !folder! mkdir !folder!
copy "%%x" !folder!
)
But I would like to be looking for the xx not only by its position in the filename, but by the specific character (underscore) and position in the filename.
Is there any way to do it?
Update - example:
I have the following files in a single folder:
My-Project_ar-SA-2016114-12h33m10s.txt
My-Project_cs-CZ-2016114-12h33m8s.text
My-Project_da-DK-2016114-12h33m10s.txt
The "template" for the filenames is "[project-name]_[language-CODE]-[dateAndTime].txt
And I want to copy the first file into a different location\ar folder (for example "C:\Output\ar"), the second file into "C:\Output\cs" etc.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
SET "destdir=U:\destdir"
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*_*-*-*.txt" '
) DO (
FOR /f "tokens=1*delims=_" %%c IN ("%%a") DO (
FOR /f "tokens=1,2*delims=-" %%q IN ("%%d") DO (
ECHO(COPY "%sourcedir%\%%a" "%destdir%\%%q\"
)
)
)
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
The required COPY commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(COPY to COPY to actually copy the files. Append >nul to suppress report messages (eg. 1 file copied)
It isn't clear whether you want the destination directory to be xx or XX. This is set up for xx for XX use %%r in place of %%q in the copy line.
Read the directory for files only using the mask _--.txt into %%a
Remove the leading characters up to the underscore by tokenising using _ and selecting %%d, the trailing portion
re-tokenise %%d on -. first token to %%q, second to %%r
Mix and match to create the copy command.
Note that your second filename, ...CZ... is a .text filename, not a .txt
According that all .txtfiles in the directory you're running the BAT are to be copied and the template is stricly what you described.
Here is an idea to do it :
#echo off
for /f "tokens=1,2,3* delims=_-" %%a in ('dir *.txt /b/a-d') do echo copy "%%a%%b%%c%%d" "c:\output\%%c"
Remove the echo before the copy if the Output is OK
Related
So for example in a directory there are files with the .test file extension
And in a batch script I would want to extract the first lines of the files to variables no matter how many files (this is where it's hard for me)
And as a test I would display (echo) the lines extracted
How would I do that?
Here's what I could make:
dir /b *.test>testfileslist.temp
find /v /c "" <testfileslist.temp>filesnumber.temp
set /p filesnum=<filesnumber.temp
del filesnumber.temp
#ECHO OFF
SETLOCAL
rem The following settings for the source directory, destination directory, target directory,
rem batch directory, filenames, output filename and temporary filename [if shown] are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
:: remove variables starting ":"
FOR /F "delims==" %%a In ('set : 2^>Nul') DO SET "%%a="
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*.txt" '
) DO (
FOR /f "usebackqdelims=" %%t IN ("%sourcedir%\%%a") DO IF NOT DEFINED :%%a SET ":%%a=%%t"
)
SET :
GOTO :EOF
for each filename found matching the filemask (I used *.txt), establish a variable with name starting : (since : cannot be in a filename) and ignore the remainder of the file.
Note that I've assumed filenames do not contain spaces, commas or any of the batch-sensitive characters.
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.
I need a batch file that when run will look into a specific folder in Program Files (86) and copy and paste that file into another folder. Now I already know the code thanks to this website.
Here is my dilemma: the file changes from computer to computer. I know the first 4 letters are xxxx then followed by an unknown amount of numbers.
Can I make a .bat file that could look for the beginning of a file name?
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\abcd*" '
) DO (
SET "name=%%~na"
SET "name=9!name:~4!"
FOR /L %%z IN (0,1,9) DO SET "name=!name:%%z=!"
IF NOT DEFINED name ECHO(COPY "%sourcedir%\%%a" "%destdir%\"
)
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
The required COPY commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(COPY to COPY to actually copy the files. Append >nul to suppress report messages (eg. 1 file copied)
after setting delayedexpansion mode, perform a directory scan of the source directory, in /b basic mode /a-d without directories and assign each filename found to %%a.
set name fom the name part only of %%a, then remove the first 4 characters and include a 9 into the modified name.
Then remove all 0 to 9 from the result, and if name becomes empty, do the copy. Note that the 9 is added so that the string name remains non-empty until the very last iteration of the for /L loop.
#echo off
pushd "c:\program files (x86)"
FOR /f "delims=" %%a IN ('dir /b /a-d "xxxx*"^|findstr /i "\\xxxx[0-9][0-9]*\."') DO (
ECHO copy "%%a" "c:\another folder\"
)
popd
(NOTE: the copy command is disabled by an ECHO. Remove the ECHO, if the output looks correct.)
filter the output of the dir command to find:
- \\ a literal \ followed by
- xxxx the known prefix followed by
- [0-9] at least one number followed by
- [0-9]* zero or more numbers followed by
- \. a literal .
Pro's: no delayed expansion needed, should be (slightly) faster than Magoo's solution
To look also into subfolders, add /s to the dir command.
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!
Using a batch file I'm trying to generate a list of only folders within a location that contain a certain file type, let's call it *.abc
at the moment I only know how to echo a DIR command output to a file called folder.lst, I would like to expand on that and try to either
a) echo only folders containing the *.abc file type to folder.lst
b) remove references in folder.lst of folders that do not contain the *.abc file type.
I also tried having a FOR loop check each line to see if a *.abc file existed in that location and skip it, if not, but I just could not get that to work, here is an example of what I had.
setlocal enableextensions enabledelayedexpansion
FOR /F "delims=" %%C in (folder.lst) do (
set temp=%%C
if not exist !temp!\*.abc (goto skip) else (goto resume)
:resume
then my actions live here
:skip
)
but I am aware I am doing something wrong here...I just do not know what.
Maybe the /R form of the for command will help:
for /r "basedir" %%a in (.) do if exist "%%~a\*.abc" (
echo %%a contains .abc file(s)
)
The %%a will be the directories you want (with a trailing \., but you should be able to not care or accommodate this).
There are problems with such of the script as you have posted in that you can'y use labels within a block statement. You've also not provided any examples.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "lastdir="
FOR /r "%sourcedir%" %%a IN (*.abc) DO IF "!lastdir!" neq "%%~dpa" (
SET "lastdir=%%~dpa"
ECHO %%~dpa
echo "!lastdir:~0,-1!"
)
GOTO :EOF
Each directory found will be echoed twice - one with the trailing \ and once without.
You would need to change the setting of sourcedir to suit your circumstances.
#echo off
setlocal enableextensions disabledelayedexpansion
set "root=%cd%"
for %%a in ("%root%") do for /f "delims=: tokens=2" %%b in ('
dir /a-d /s "%root%\*.abc" ^| find "\"
') do echo(%%~da%%~pnxb
This executes a recursive dir command searching for the indicated file type under the starting point (change root variable to suit your needs). For each found folder we retrieve the folder from the dir header that precedes the file list (the lines that contain a backslash).
To separate the path from the rest of the information in the line, the colon is used as delimiter. As this will leave the drive out of the retrieved information, an aditional for is used to retrieve the drive from the folder reference.
From the command line:
for /f "delims=" %a in ('dir /s /b *.abc') do echo %~dpa >> folders.lst
In a batch file:
for /f "delims=" %%a in ('dir /s /b *.abc') do echo %%~dpa >> folders.lst
The above commands will place only the folder names containing the *.abc files in folders.lst.
Notes:
% should be replaced by %% when the command is used in a batch file.
The ~dp part of %~dpa expands %a to a drive letter and path only. Remove the d if you don't want the drive letter. The p path includes a trailing \ which may be interpreted as an escape character by some commands.
The above commands start the search in the current directory. To search from the root of the current drive you can do cd \ first.
For more information see FOR /F Loop command: against the results of another command and Parameters.