Using a for loop in a batch file, from a folder full of xml files, I am trying to parse an xml tag but also the file name of the current file being read.
I have searched and this question seems to be the same as mine, but for linux. I am using windows
Can I get the name of the file currently being read in a for loop?
From other answers on the forum I have put together this, but unsuccessful.
for %%a in (*.xml) do (
for /f "delims=<> tokens=3" %%b in ('findstr /i /c:"<description>" *.xml') do (
echo %%~na^|%%b>>output.txt
)
)
Is it possible to get the xml tag and echo the file name of the file the tag was read from?
kind of like:
for /f "delims=<> tokens=3" %%b in ('findstr /i /c:"<description>" *.xml') do (
echo %~n0^|%%b>>output.txt
)
Except that will echo the bat file name, not the xml name.
Example final output desired (xml name|xml tag)
Atari 2600|Air Raid
Atari 2600|Airlock
Atari 2600|Alien
Nintendo Game Boy|Addams Family
Nintendo Game Boy|Adventure Island
Sega 32X|Blackthorne
Sega 32X|Mortal Kombat II
Appreciate any advice as I am just teaching myself here, I don't mind just being steered in the right direction either.
for /f "delims=<> tokens=3" %%b in ('findstr /i /c:"<description>" "%%a"') do (
should work for you. The current filename is in %%a. Your code would attempt to find the string in all .xml files.
Perhaps findstr /m /i /c:<description>" *.xml may give you a workable base (as a command - not as a replacement findstr command for your batch).
Supplementary after comment
SET "varlist=applicationpath missing notes junk"
FOR %%a IN (%filename1%) DO (
FOR %%w IN (%varlist%) DO SET "%%w="&for /f "delims=<> tokens=3" %%b in ('findstr /i /c:"<%%w>" "%%a"') do SET "%%w=%%b"
)
:: Show resulting values from file
FOR %%w IN (%varlist%) DO SET %%w
I'm assuming that you are using %%a as you will to set up the .xml filename - I just used a fixed text file as the source for testing.
Simply establish a list of the variables you wish to extract and alter the string that findstr locates in the file. Set the variablename to the value from the located line. If not located, leave set to nothing (which is easily tested with an if defined variablename command)
Related
I'm trying to automate renaming of files based on a CSV such as the one shown below:
Name,FullName
John,JohnDoe
Jane,JaneDoe
Joe,JoeDoe
Let's say I have 3 text files within the same folder of my .bat called John.txt, Jane.txt, Joe.txt and I want to rename John.txt to JohnDoe.txt, etc.
I am getting "The system cannot find the file specified" no matter how much I alter the filepath in my rename. Here is a basic rundown of what I have. What am I doing wrong here or what other way should I approach this? I appreciate all feedback.
#echo off
setlocal enabledelayedexpansion
set csvpath=C:\Users\user1\OneDrive\Documents\BatchExamples\stuff.csv
FOR /F "usebackq skip=1 tokens=1,2 delims=," %%g IN (!csvpath!) do (
set person=%%g
set name=%%h
echo My name is !person! and my full name is !name!
rename !person!.txt !name!.txt
)
pause
This is how I would do it:
#echo off
set "csvpath=C:\Users\user1\OneDrive\Documents\BatchExamples\stuff.csv"
FOR /F "usebackq skip=1 tokens=1,2 delims=," %%g IN (`findstr /v /c:":-:-:" "%csvpath%"`) do (
echo My name is "%%g" and my full name is "%%h"
rename "%~dp0\%%g.txt" "%%h.txt"
)
pause
This code is a bit cleaner and more robust, in that file paths and names can have special characters (like &) without breaking the script.
findstr /v /c:"SEARCHSTRING" "FILEPATH" tells findstr to print every line within FILEPATH excluding (/v) lines with SEARCHSTRING. This doesn't really change much from what you had previously, however it is a bit more robust.
In the rename command, I set it to %~dp0 and then the file name, %~dp0 is the path to where your .bat script is.
Currently my code is: findstr Starfy ./List.txt > result.txt
My result.txt is
3841 - Legendary Starfy, The (USA).zip
x166 - Legendary Starfy, The (USA) (Demo) (Kiosk).zip
However, I want result 1 and result 2 to have their own seperate files, so it would look like:
result1.txt > 3841 - Legendary Starfy, The (USA).zip
result2.txt > x166 - Legendary Starfy, The (USA) (Demo) (Kiosk).zip
I'm unsure how to make this work, and would love if someone is able to help point me in the right direction.
This works:
#echo off
for /F "tokens=1* delims=:" %%a in ('findstr "Starfy" .\List.txt ^| findstr /N "^"') do >result%%a.txt echo %%b
Just pass your original results into another instance of findstr /N command that add line numbers. After that, separate the number and the line in a for /F command and output each line to its corresponding numbered file...
for /f "tokens=1,* delims=:" %%S in ('findstr /i "echo" "%~f0"^|findstr /n /i "echo" ') do ECHO %%T>"U:\moreresults\result%%S.txt"
The command quoted in parentheses finds a string (in this case, echo) ignoring case (/i) within the file "%~f0" (this batch file, which contains a heap of standard code I use for testing). This is passed to another instance of findstr, this time looking for the same string, but numbering the lines (as serialnumber:linetext).
The resultant text is tokenised using : as a separator, so %%S receives the serialnumber and %%T receives the rest of the line (token *). Then simply build the result filename using %%S and write the text part of the line to it.
The caret is used to escape the pipe so that cmd knows that the pipe is part of the command-to-be-executed, not of the for command.
Assuming that you do not already have files in the location you're outputting your results, which could alalready be named using that intended naming scheme, then something like this may suit you:
#Echo Off
SetLocal EnableExtensions EnableDelayedExpansion
Set "i=0"
For /F Delims^=^ EOL^= %%G In (
'%SystemRoot%\System32\find.exe /I "Starfy" 0^<".\List.txt" 2^>NUL'
) Do (
Set /A i += 1
1>"Result!i!.txt" Echo %%G
)
Please note that I used find.exe instead of findstr.exe simply because your example used a simple string containing a series of alphabetic only characters. Feel free to change it to '%SystemRoot%\System32\findstr.exe /LIC:"Starfy" ".\List.txt" 2^>NUL', or similar, should you require a more specialized matching mechanism.
I have several .csv files in one folder. They are saved automatically but with spaces and execution date and time (in seconds) with amount of containing lines.
So far I was not able to run my powershell script with files containing spaces. So I tried to rename filenames using batch. so far nothing is working fine. Either in cmd-line or with a batch file.
Trying to loop in folder to find .csv is working but defining a string and then substring parts of the file not.
for %%i in ('dir *.csv /b /s') do set string = %%~ni
set substr=!string:~20,25!
echo !substr!
I tried first to use % instead of ! but didn't worked as well. Tried to use pipes for the loop as well, didn't worked.
So far my output is just
!string:~20,25!
My output has to be just the "real" filename of the report without anything else before or after it.
For example, do with that path and filename
C:\Users\Username\CSV_Files\Reportoutput Report_2017 2018-01-09T07_10_33.1924R.csv
this
C:\Users\Username\CSV_Files\Report_2017.csv
When I'm able to extract just the filename without any spaces or leading chars like "Reportoutput" (which is always the same) or starting time of report or containing lines in the report I could use that string and combine it with the path where files are saved.
Any ideas? Why is my "substring" not working at all? Do I miss some action? Some code?
I'm using windows.
Based on the file name structure you've presented and looping in one folder, (the current directory), as stated and used in your example code:
#Echo Off
For %%A In ("* * *.csv"
) Do For /F "Tokens=2" %%B In ("%%~nA") Do Ren "%%~A" "%%B%%~xA"
If you wanted to check inside subfolders of the currect directory then change it to this:
#Echo Off
For /R %%A In ("* * *.csv"
) Do For /F "Tokens=2" %%B In ("%%~nA") Do Ren "%%~A" "%%B%%~xA"
…and if you want to specify the base directory name then you can do so like the following two examples which use %UserProfile% for demonstration purposes, (change as appropriate).
#Echo Off
For /R "%UserProfile%" %%A In ("* * *.csv"
) Do For /F "Tokens=2" %%B In ("%%~nA") Do Ren "%%~A" "%%B%%~xA"
and:
#Echo Off
CD /D "%UserProfile%" 2>Nul||Exit /B
For /R %%A In ("* * *.csv"
) Do For /F "Tokens=2" %%B In ("%%~nA") Do Ren "%%~A" "%%B%%~xA"
Instead of splitting the names using character numbers, this simply takes the second token of the file name string delimited by spaces and adds the original file extension to it in a rename command.
How do you trim the date from a text file. For example, I have multiple files like:
test_MX_abc_20091011.txt
test_MX_pqrdhdsu_20091011.txt
test_MX_xyieuz_20091011.txt
All files will have test_MX in common but the 3rd part will of different size.
I would like to change into:
test_MX_abc.txt
test_MX_pqrdhdsu.txt
test_MX_xyieuz.txt
I know how to change the file if name is like test_20091011.txt with the below code, But if name has more string along with date, how to do that?
for /F "tokens=1 delims=_" %%i in ("%%~na") do (
move /Y %%~fa %data_in%\%%i%%~xa >nul
)
Thanks in advance.
This rename operation can be done for example with:
#echo off
for /F "tokens=1-3* delims=_" %%A in ('dir /A-D /B test_MX_*.txt') do (
ren "%%A_%%B_%%C_%%D" "%%A_%%B_%%C.txt"
)
Each file name is separated into 4 strings assigned to loop variables A to D with using underscore as separator. The loop variable D takes everything of file name after third underscore.
Or also working for the 3 files:
#echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%F in ('dir /A-D /B test_MX_*.txt') do (
set "ActFileName=%%~nF"
set "NewFileName=!ActFileName:~0,-9!"
ren "%%~F" "!NewFileName!.txt"
)
endlocal
This solution assigns the name of a file without file extension and path to environment variable ActFileName. Next a new environment variable with name NewFileName is defined with name of active file without the last 9 characters (underscore and date string). This modified file name is used next in the rename operation.
Other solutions using commands for, set and ren can be found on Stack Overflow.
Search with the string
[batch-file] for set rename files
and more than 600 results are presented all using more or less something like above.
For details on the used commands, open a command prompt window, execute one after the other following commands and read output help.
dir /?
for /?
ren /?
set /?
I need to generate lists of all files that has been created, modified and accessed respectively on a windows system.
I have found the command forfiles here http://technet.microsoft.com/sv-se/library/cc753551(v=ws.10).aspx but apparently this does not use the created and accessed timestamps, I need those also (in separate lists).
I have also looked into using the dir command but I have only found references to sorting and not filtering in the help sections.
Your question have some unclear details, so I made some assumptions.
The Batch file below create three separated text files: created.txt, modified.txt and accessed.txt, with the lists of the files in current folder; each list have the respective date in YYYYMMDDHHMMSS format followed by the file name, so it may be easily processed.
#echo off
setlocal DisableDelayedExpansion
for %%f in (created modified accessed) do if exist %%f.txt del %%f.txt
set "folder=%CD:~2%"
for /F "skip=1 tokens=1-3*" %%a in (
'"wmic datafile where (path='%folder:\=\\%\\') get InstallDate, LastModified,
LastAccessed, Name"'
) do (
for /F "delims=." %%A in ("%%a") do echo %%A %%d>> created.txt
for /F "delims=." %%B in ("%%b") do echo %%B %%d>> modified.txt
for /F "delims=." %%C in ("%%c") do echo %%C %%d>> accessed.txt
)
rem Process each list this way:
for /F "tokens=1*" %%a in (created.txt) do echo %%a - %%b
In the subject there was also "between dates" :) How about that?
forfiles doesn't allow to put 2 date conditions ('+' and '-').
I also have a problem with a date condition with unequalness in wmic.
for example:
wmic datafile where (path='%folder:\=\\\\%\\\\' and lastmodified ^> "20120713" and lastmodified ^< "20120714") get Name
returns nothing (I needed an escape ('^') before '<' and '>' to run the command).
wmic datafile where (path='%folder:\=\\\\%\\\\' and lastmodified ^> "20120713") get Name
returns only files modified after 20120714000000 (in the wmic notation).