I have a folder of 9000 files named XX-randomString-numbers.jpg, where XX is an ID number I need.
I need to export it to a CSV list of [ XX | filename.jpg ] so that I can work with it in SQL.
So far, I have pieced this together:
Setlocal Enabledelayedexpansion
for %%A in ("C:\...\imageImport\*.jpg")
do (
set "str=%%~nA"
for /f "delims=-" %%a in ("%str%")
do set part=%%a
echo.%part%
)
#Echo off
Setlocal Enabledelayedexpansion
( Echo ID^|Filename
for %%F in ("C:\...\imageImport\*.jpg"
) do for /f "delims=-" %%I in ("%%F"
) do set Echo %%I^|%%F
) >Out.csv
You are enabling delayed expansion but you are not using it. Anyway, you do not need it in your code, because you do not really need any interim variables. What you do need though is to correct the syntax of the for loops and remove the superfluous line-breaks in front of do.
So here is the fixed code:
for %%A in ("C:\...\imageImport\*.jpg") do (
for /F "delims=- eol=-" %%a in ("%%~nA") do (
echo(%%a^|%%~nA
)
)
To write the result into a file output.csv, use this:
#echo off
> "output.csv" (
for %%A in ("C:\...\imageImport\*.jpg") do (
for /F "delims=- eol=-" %%a in ("%%~nA") do (
echo(%%a^|%%~nA
)
)
)
The eol=- option is specified for the for /F loop not to ignore files beginning with the default eol character ; and so, the eol option is effectively deactivated, because eol becomes hidden behind delims as the same character is given.
Related
I cannot get this to work. I am reading an XML file line by line and then look at each line if it contains a specific tag <assemblyIdentity name="PostDeploymentAction" version". When I find it, I would modify it and write everything back into a file.
However, I can not find the tag since it contains quote marks.
#ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
....some more code....
SET dllFile=%DestPath%\%ProjectName%.dll.manifest
IF NOT EXIST "%dllFile%" (
ECHO File %ProjectName%.dll.manifest does not exist^^!
GOTO ERROR
) ELSE (
ECHO Modifying %ProjectName%.dll.manifest in directory:
ECHO %DestPath%
REM Create a temporary file in the folder, where this batch file is being executed from
>"temp.xml" (
FOR /F "usebackq delims=" %%I IN ("%dllFile%") DO (
SET "line=%%I"
REM Insert existing line before modification
SETLOCAL DisableDelayedExpansion
ECHO %%I
ENDLOCAL
REM Find correct version number
SET "myVariable=<assemblyIdentity name="PostDeploymentAction" version"
IF not "!line!"=="!line:myVariable=!" (
echo !line!
)
....some more code....
)
)
)
Whatever escape characters I use, it will not find this particular line (or it finds every line). Everything else in above code works fine - only IF not "!line!"=="!line:myVariable=!" does not. Any help much appreciated.
Thanks
Use another method to compare the strings:
#echo off
setlocal enabledelayedexpansion
; set "myvariable=<assemblyIdentity name="PostDeploymentAction" version"
set myvariable
for /f "delims=" %%a in (test.txt) do (
echo "%%a"|findstr /c:"!myvariable:"=\"!">nul && (
echo DEBUG: found %%a
REM do something special here
) || (
echo %%a
REM write line unchanged
)
)
(you have to escape the doublequotes with findstr; findstr` uses the backslash as escape character)
In the end, I ended up with
SET "xmlTag=<assemblyIdentity name="PostDeploymentAction"
FOR /F "usebackq delims=" %%A IN ("%dllFile%") DO (
ECHO "%%A"|FINDSTR /c:"!xmlTag:"=\"!">nul && (
FOR /F "tokens=2,3 delims=^=" %%B IN ("%%A") DO (
SET version=%%C
SET version=!version:~0,-9!
ECHO Found PostDeploymentAction.dll version number !version!
)
)
)
This gives me the version number I was after. The full XML line is <assemblyIdentity name="PostDeploymentAction" version="1.1.0.0" language="neutral" processorArchitecture="msil" />. The first FOR loop gets the entire line out of the XML file, while the second FOR gets the actual version number "1.1.0.0".
The second FOR is a bit weird, but it works. However, I am sure there are better ways...
BTW, the above was a bit slow since FINDSTR is called for each line of the file (read file line by line and then analyze each line with FINDSTR).
There is a much, much faster version by calling FINDSTR only once for the entire file and then analyzing the return result found by FINDSTR.
SET "xmlTag=<assemblyIdentity name="PostDeploymentAction"
FOR /F "tokens=*" %%A in ('FINDSTR /c:^"!xmlTag:"=\"!^" ^"%dllFile%^"') DO (
FOR /F "tokens=5 delims=^=^ " %%B IN ("%%A") DO (
SET version=%%B
ECHO Found PostDeploymentAction.dll version number !version:~1,-1!
)
)
I have file s_result.txt as:
AAA,BBB,CCC
DDD,EEE
FFF,GGG
HHH,III,JJJ
...
And I try to get the sf_result.txt like this:
AAA,BBB
AAA,CCC
DDD,EEE
FFF,GGG
HHH,III
HHH,JJJ
...
I used script as below:
REM Transfer s_result.txt to sf_result.txt
DEL sf_result.txt
Echo. 2>sf_result.txt
for /F "tokens=1,2,3 delims=," %%a in (s_result.txt) do (
If %%c EQU [] (
ECHO %%a,%%b>>sf_result.txt
) else (
ECHO %%a,%%b>>sf_result.txt
ECHO %%a,%%c>>sf_result.txt
)
)
I got this result.txt instead:
AAA,BBB
AAA,CCC
DDD,EEE
DDD,
FFF,GGG
FFF,
HHH,III
HHH,JJJ
...
How can I get the right result?
Thanks,
If you want to parse line-by-line, use for /F. If you want to tokenize word-by-word on a single line, use for without the /F. Also, in a basic for loop, Windows already tokenizes on unquoted commas with no need to specify a delimiter. (It also tokenizes on spaces, tabs, and semicolons.) With this in mind, the solution is actually pretty simple.
#echo off & setlocal
for /f "usebackq tokens=1* delims=," %%I in ("test.txt") do (
for %%x in (%%J) do (
echo(%%I,%%x
)
)
Output:
AAA,BBB
AAA,CCC
DDD,EEE
FFF,GGG
HHH,III
HHH,JJJ
There have already been great answers provided with some smart approaches.
However, I want to stick to the code you posted here.
The main problem is the line if %%c EQU [], because it compares the third token with the literal string []; the third token can be CCC, JJJ, or an empty string, according to your example, so the condition is never going to be fulfilled.
To correct that, you should write if "%%c"=="" instead.
You could further improve your script by doing a single redirection > to the output file rather than creating it in advance and appending multiple times; just put the entire for /F loop in between parentheses and redirect the whole block.
So here is the corrected and improved code:
rem Transfer s_result.txt to sf_result.txt
> "sf_result.txt" (
for /F "usebackq tokens=1-3 delims=," %%a in ("s_result.txt") do #(
if "%%c"=="" (
echo %%a,%%b
) else (
echo %%a,%%b
echo %%a,%%c
)
)
)
The # symbol prevents command echoes of the loop body to be written to the output file as well. If there is #echo off placed at the beginning of your script you do no longer need that symbol.
Of course this code cannot handle lines with more than three tokens correctly.
I do like rojos clever approach (+1).
To overcome the implications he mentions I think of a recursive approach.
:: Q:\Test\2018\06\28\SO_51073893.cmd
#echo off & setlocal
for /f "usebackq tokens=1-2* delims=," %%A in ("test.txt") do Call :Sub "%%A" "%%B" "%%C"
Goto :Eof
:Sub
Echo %~1,%~2
if "%~3" neq "" for /f "tokens=1* delims=," %%D in (%3) do Call :Sub %1 "%%D" "%%E"
With a slightly changed file test.txt I get this output:
> SO_51073893.cmd
AAA,B=B
AAA,C;C
DDD,EEE
FFF,GGG
HHH,I I
HHH,JJJ
In my opac_one-hit*.log I have 3 columns with numbers which are separated with ;
I want to find and rename the duplicated numbers in the third column and make the repeated numbers look like number_1... number_2
#ECHO OFF
SETLOCAL enabledelayedexpansion
for /r %%# in ("opac_one-hit*.log") do (
FOR /F "usebackq skip=3 tokens=1,3 delims=;" %%G IN ( "%%~f#" ) DO ( echo %%H >> liste.txt
)
)
Sample from opac_one-hit*.log:
"F96B1606";"216618711"; "BV499630491";
"F96B1607";"216618878"; "BV499630823";
"F96B1661";"216653304"; "BV49843883X";
"F96B1690";"216796148"; "BV49843883X";
Result:
the duplicated number in the third column should look like this "BV49843883X_1" If there are two duplicates then BV49843883X_1 and BV49843883X_2
You did not specified the desired output. This Batch file is a starting point:
#echo off
setlocal EnableDelayedExpansion
for %%# in ("opac_one-hit*.log") do (
for /F "usebackq tokens=3 delims=; " %%G in ("%%~f#") do (
echo "%%~G!N3[%%~G]!"
set /A "C3[%%~G]+=1"
set "N3[%%~G]=_!C3[%%~G]!"
)
)
This is the output:
"BV499630491"
"BV499630823"
"BV49843883X"
"BV49843883X_1"
Sadly you haven't shown exactly what your output should be, so I'll have to leave it to you to complete the task.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:: remove variables starting #
FOR /F "delims==" %%a In ('set # 2^>Nul') DO SET "%%a="
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q49821253.txt"
SET "outfile=%destdir%\outfile.txt"
REM for /r %%a in ("%filename1%") do (
for %%a in ("%filename1%") do (
FOR /F "usebackq tokens=1,3 delims=;" %%G IN ( "%%~fa" ) DO (
CALL :bumpcount %%H
)
)
GOTO :EOF
:bumpcount
SET "col3=%~1"
(
IF DEFINED #%col3% (
SET /a #%col3%+=1
ECHO "%col3%_!#%col3%!"
) ELSE (
echo %1
SET /a #%col3%=0
)
)>> "%outfile%"
GOTO :eof
Note that I've changed the filenames to suit my system, removed the skip from the file-analyser and replaced the for/r with a plain vanilla for for testing.
The for /f to remove variables starting # needs to be moved to the line before the for...%%G... if you want to restart the numbering at the start of each new file. Don't use ::-comments within a loop, use REMcomments instead.
First, clear all # variables. then, on each line, pass column3's contents to a subprocedure called :bumpcount
:bumpcount sets the variable col3 to the value of column3, removing the enclosing quotes. If the variable #+column3 is defined, then we have encountered this value in the past, so increment it and append the new count-of-repeats to the contents of column3; otherwise, just output the value as suplied and set %+column3 to 0, indicating that it's been seen before and starting the count for that particular value's suffix.
Note the (...) surrounding the if defined statement. This gathers all output to the redirected destination.
Since you didn't explicitly show the desired output, I simply reproduced column3 without the terminal ; as I assume it appeared from your original code.
I am trying to create batch file that reads specific CSV documents from specific file, and extracts some lines that have specific number and print it out on the screen " the whole line !". The problem is I created the code but it wont work at all, whenever I tried it only prints the line numbers!?
The code:
#echo off
setlocal EnableDelayedExpansion
set "yourDir=C:\Users\Adminm\Desktop\test11\"
set "yourExt=csv"
set "keyword=44"
set /a count=0
set linenum=!count!
set c=0
pushd %yourDir%
for %%a in (*.%yourExt%) do (
for /f "usebackq tokens=3 delims=," %%b in (%yourDir%%%a) do (
set /a count = !count! + 1
if NOT %%b == %keyword% (
for /f "delims=" %%1 in ('type %yourDir%%%a') do (
set /a c+=1 && if "!c!" equ "%linenum%" echo %%1%
)
)
)
)
echo !count!
popd
endlocal
thanks in advance <3
for %%a in (*.%yourExt%) do (
for /f "usebackq delims=" %%L in ("%%a") do (
for /f "tokens=3 delims=," %%b in ("%%L") do (
if %%b == %keyword% echo %%L
)
)
)
Assuming what you want to do is scan each file for a target string in column3, then:
Since you have already changed to yourdir, there's no requirement to specify it in the scan-for-filenames for.
Your attempt to locate the required line is clumsy. All you need to do is assign each line in turn to a metavariable (%%L) and then use for/ to parse the metavariable. When the required data matches, simply echo the metavariable containing the entire line.
You've attempted to use %%1 as a metavariable. %n for n=0..9 refers to the parameter number supplied to the routine. The only officially defined metavariables for use here are %%a..%%z and %%A..%%Z (one of the very few places where batch is case-sensitive) - although some other symbols also work. Numerics will not work here.
I want to make a generic script which will convert a fixed width flat file into csv. Below is my approach:
`echo off
setlocal EnableDelayedExpansion
echo a,b,c>final.txt
for /f "tokens=1 delims=;" %%i in (source.txt) do (
set x=%%i
for /f "tokens=1,2 delims=," %%a in (config.txt) do (
call SET VAR=!x:~%%a,%%b!
for %%p in (!VAR!) do (echo/|set /p ="%%p,"
) >>final.txt
)
)
`
Config file which I am using contains the parameters for substring which states from where to do the substring and how many characters.
Config file contains:
0,9
9,3
12,11
23,7
30,1
31,1
32,5
37,9
46,9
55,3
58,9
67,9
76,9
85,9
94,1
Source file contains the actual fixed with source.
Now with my code I am getting the result but for the fields which has no value/empty in the source is not reflecting in the final output.
Example:
Source:
1234<space>678 [col1=678,col2=space,col3=678]
Output (Current):
1234,678
Output(Expected):
1234,,678
Please help
Your for %%p in (!VAR!) do (…) loop executes defined (…) command for all strings found in !VAR! delimited with white space(s). So if !VAR! results to all white spaces, then consequential for %%p in ( ) do (…) loop executes nothing. Next code snippet could help:
echo off
setlocal EnableDelayedExpansion
echo a,b,c>final.txt
rem replace the €€€ string with any unused one
set "fooString=€€€"
for /f "tokens=1 delims=;" %%i in (source.txt) do (
set "x=%%i"
for /f "tokens=1,2 delims=," %%a in (config.txt) do (
call SET "VARraw=!x:~%%a,%%b!%fooString%"
rem replaced with respect to the OP's comment: for %%p in (!VARraw!) do (
for /F "tokens=*" %%p in ("!VARraw!") do (
set "rav=%%p"
set "var=!rav:%fooString%=!"
echo/|set /p "=!var!,"
) >>final.txt
)
)
Edit: note that for /F "tokens=*" %%p in ("!VARraw!") do ( would remove leading spaces from the !VARraw! string.