Im trying to build a batch file.
I have 30 csv files in a folder
My intention is
Get each file name (Example is 097_021216_192332.csv)
Extract the first 3 digits
Compare it with a lookup table ( lookup1.bat) against which i have marked another string
EG: lookup1.bat
#echo 107=B_05-
#echo 097=B_06-
#echo 149=B_07-
#echo 109=B_08-
#echo 101=B_09-
#echo 105=B_10-
#echo 098=B_11-
So here i will get "B_06-"
Modify the file name with this "B_06-" prefix and rename the file
Here is my code , i have only basic ideas about looping and im struggling a lot.Thanks for any help.
#echo on
setlocal enabledelayedexpansion
for %%a in ("*.csv") do (
set FileName=%%~na
goto:stepa
goto:eof
)
:stepa
for /f "tokens=1 delims=_" %%a in ("%FileName%") do (
set A=%%a
echo %A%
)
#SET MN=%A%
#FOR /F "tokens=1,2 delims==" %%i IN ('lookup1.bat') DO #IF %%i EQU %MN% SET MW=%%j
#ECHO The board number corresponding to %MN% is %MW%.
set "str=%MW%%FileName%"
echo "%str%"
Ren "!FileName!" "!str!"
:eof
You have a series of problems with the structure of your program. If you want to call a subroutine from inside a for command the right way is using call, not goto, and the goto :eof command must be placed after the for ends. However, this code is simple enough so it don't requires a subroutine.
The table lookup method is more efficient (and also simpler, IMHO) if you use an array to load the table just once, and then directly access its elements via an index.
#echo off
setlocal EnableDelayedExpansion
rem Create the lookup file with lookup1.bat file,
rem this program create lines like this one:
rem 097=B_06-
call lookup1.bat > lookup1.txt
rem Load the lookup table from the file,
rem this method create _array elements_ like this one:
rem set "table[097]=B_06-"
for /F "tokens=1,2 delims==" %%a in (lookup1.txt) do set "table[%%a]=%%b"
rem Process the files in current folder,
rem file name format is this:
rem ###_restOfFileName.csv
for /F "tokens=1* delims=_" %%a in ('dir /A:-D /B *.csv') do (
#ECHO The board number corresponding to %%a is !table[%%a]!.
ren "%%a_%%b" "!table[%%a]!%%b"
)
You may test if the board number is not defined for a file via an additional if not defined table[%%a] ... command placed inside the for.
You may directly create the lookup1.txt file with your text editor; just eliminate all these #echo parts from lookup1.bat and change the extension.
You may review a detailed explanation on array use in Batch files at this answer.
Related
Here's what I'm trying to do:
Loop through all files in a directory
Loop through every other line, starting with the first (all odd-numbered lines), and get the number in the line.
Write the number and the next line to an output.txt file
The data looks like this:
> 234.01 Burgeron/ Tom Tom Burgeron
Here is some information.
> 126.00 Waka/ Judy Judy Waka
Here is some more information.
I'm trying to make it look like this:
"234.01","Here is some information."
"126.00","Here is some more information."
Here's the batch file I'm writing:
#ECHO off
SETLOCAL EnableDelayedExpansion
//Loop through all files in folder
for /f "tokens=*" %%a in (*) do (
CALL :GetNumber %%a
echo "!num!",%%a
) >> FILEOUTPUT.txt
//Get number on the odd-numbered lines
:GetNumber
for /f "tokens=1 delims=>" %%a in (%1) do (
set "num=%%a"
)
I'm having trouble getting every other line of the file and then reading the next line/writing it into the file. I've seen how to skip specific lines, but not how to skip every other. How do I then take the next line?
This batch file is a bit complicated for me. Any help would be greatly appreciated. Thank you.
To show one way to alternate processing the lines:
#ECHO off
SETLOCAL EnableDelayedExpansion
REM Loop through all files in folder
for %%a in (*) do for /f "delims=" %%b in (%%a) do (
if defined num (
echo "!num!","%%b"
set "num="
) else (
for /f "tokens=1 delims=> " %%c in ("%%b") do set num=%%c
)
)
Note the above script can't reside in the folder containing the data files, or it will be processed as data.
I have files that look like that:
1989_Footer.gif
1989_Header.gif
260273_Footer.gif
260273_Header.gif
...
and I have a CSV that looks like this:
1989;10773387
260273;10776516
...
I want to rename the files number with the one given in the CSV. The first number in the CSV is the old number and the second one (after the semicolon) is the new number. How can I achive that without touching the text after the underline?
I thought about getting the file name, then search the number in the CSV and replace it with the value in the same line after the semicolon.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q40908252.txt"
FOR /f "usebackqtokens=1*delims=;" %%a IN ("%filename1%") DO (
FOR /f "tokens=1*delims=_" %%r IN ('dir /b /a-d "%sourcedir%\%%a_*"') DO (
ECHO(REN "%sourcedir%\%%r_%%s" "%%b_%%s"
)
)
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
I used a file named q40908252.txt containing your data for my testing.
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.
Read the csv file, using ; as the delimiter, placing the from-prefix in %%a and the to-prefix in %%b.
Perform a directory list of files named "%%a_anything" in the source directory, tokenise on _ so that the first token (which must be %%a) goes to %%r and the remainder-of-name to %%s, then rename the file with the prefixes switched.
Assumes that the first _ in the filename will never be a multiple-_
My JREN.BAT regular expression renaming utility can simplify the solution. JREN.BAT is pure script (hybrid batch/JScript) that runs natively on any Windows machine from XP onward - no 3rd party exe file required. Full documentation is available from the command line via jren /?, or jren /?? for paged help.
From within a batch script:
#echo off
for /f "delims=; tokens=1,2" %%A in (rename.csv) do call jren "^%%A_" "%%B_" /fm *.gif
From the command line:
for /f "delims=; tokens=1,2" %A in (rename.csv) do #jren "^%A_" "%B_" /fm *.gif
I would probably do it like that (see the explanatory remarks rem):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_CSV=%~dpn0.csv" & rem // (path to the CSV file holding the old and new numbers)
set "_LOC=%~dp0" & rem // (path to the directory containing the files to rename)
set "_PAT=*.gif" & rem // (pattern of the file name part after the first `_`)
rem // Walk through the CSV file line by line and read old and new numbers:
for /F "usebackq tokens=1-2 delims=,;" %%K in ("%_CSV%") do (
rem // Search files whose names begin with the old number and an `_`:
for /F "delims=" %%F in ('dir /B /A:-D "%_LOC%\%%K_%_PAT%"') do (
rem // Store current file name into variable:
set "NAME=%%F"
rem // Toggle delayed expansion to not lose any `!` in the file name:
setlocal EnableDelayedExpansion
rem // Rename current file by replacing the old number by the new one:
ECHO ren "%_LOC%\!NAME!" "%%L_!NAME:*_=!"
endlocal
)
)
endlocal
exit /B
Remove the upper-case ECHO command after having successfully tested the script!
The advantage of this method is that it works even in case the file name part after the first _ begins with an _ as well; so a file name 1989__some_name.gif would become renamed to 10773387__some_name.gif, so the two consecutive __ are maintained.
I need some help and guidance.
I have the script below that looks for csv files in a folder. Grabs the file name and header of the file to an output file.
The scripts works, but the header is getting chopped at the end of the line in the output file. how do I pipe the entire header to the output file?
#ECHO OFF &SETLOCAL
for %%a in (*.csv) do (
set "line="
set /p "line="<"%%~a"
SETLOCAL ENABLEDELAYEDEXPANSION
echo %%a %line%":">>output.txt
echo(!line!>> output.txt
endlocal
)
It depends on how long your csv headers are.
In your code, you are reading the header using redirected input and set /p. This method allows a maximum input of 1022 characters.
You can use a for /f to read the files, but this is also limited to the max command line length, in this case 8192 characters.
#echo off
setlocal enableextensions disabledelayedexpansion
(for /f "tokens=1,2,* delims=:" %%a in ('
findstr /n "^" *.csv ^| findstr /b "[^:]*:1:"
') do (
echo(%%a:
echo( %%c
)) > output.txt
This code simply read input files with a findstr command, numerate output lines and from this output retrieve only the first line for each file. The for /f splits the lines using colons to retrieve the first three tokens in the lines: the file name, the line number and the line contents.
edited to adapt to comments
As pointed, there is a limit and the real data has collided with it.
I don't see a bulletproof pure batch solution, but a hybrid file can handle the problem
#if (#This==#IsBatch) #then
#echo off
setlocal enableextensions disabledelayedexpansion
call :getBatchFileReference _f0
(
for %%a in (*.csv) do (
echo %%a
<"%%a" cscript //nologo //e:Jscript "%_f0%"
)
) > output.txt
goto :eof
:getBatchFileReference returnVar
set "%~1=%~f0"
goto :eof
#end
WScript.StdOut.WriteLine(WScript.StdIn.ReadLine());
Saved as .cmd or .bat, the file contains an initial zone with batch code and a final zone with javascript code.
For each csv file, the batch part will redirect it as input to the javascript part to read the first line and output it.
SO I have a CSV file that looks like the such:
ComputerName,UserID,192.168.0.xx
ComputerName,UserID,192.168.0.xx
I am trying to write a batch loop script that will read the IPs that are in the script and ping them this is what I have so far:
setlocal Disable DelayedExpansion
for /f "tokens=1,2,3 delims=" %%a in (test.csv) do(
Set line=%%c
ping %line%
)
Setting the variable works, but it seems like I am not able to read anything from the batch file as I am getting returned an error that says :
%%a was unexpected at this time
I was wondering how can I be able to fix that or what am I doing wrong here
There are a few issues, but you are very close. I have updated your script and noted the corrections.
REM You want to _Enable_ delayed expansion. This is a single word.
setlocal EnableDelayedExpansion
REM Your delimiter needs to be a ,
for /f "tokens=1,2,3 delims=," %%a in (test.csv) do (
Set line=%%c
REM You need to access the line value enclosed in !'s since it is delayed expansion.
ping !line!
)
Alternately, you could do this as a one-liner from the command prompt (no batch file needed):
FOR /F "tokens=1,2,3 delims=," %a in (test.csv) do PING %c
The delims= bit means that there are no delimiters and so the entire string is treated as one unbroken line instead of being split on the comma like you want. Change it to
setlocal EnableDelayedExpansion
for /f "tokens=1,2,3 delims=," %%a in (test.csv) do (
Set line=%%c
ping !line!
)
I have read this thread, which helped, but doesn't answer my specific question. I'm hoping someone can help.
I am trying to export a CSV file with TWO COLUMNS of data. Column 1 is the actual filename (with extension), and Column 2 would be the immediate Folder Name (without any path info) of the file location. Question I have is, is that possible? Next question is, how can I export this as a CSV file with two columns of information?
This is a good starting point except this only has the filename (doesn't have the second column that shows the immediate folder name), and this doesn't seem to return to the next line for each filename. Instead this is simply separating with commas and not returning to new lines.
Can you advise if this is possible and offer some ideas?
#echo off
<nul (
for /f "eol=: delims=" %%F in ('dir /b /o:n') do set /p =""%%F","
) >fileList.csv
Thanks everyone!
If by the "Immediate folder name" you mean the name of the containing directory but without the path to that directory, then:
#ECHO OFF
SETLOCAL
PUSHD "%~1"
FOR /f "delims=" %%i IN ("%cd%") DO SET directory=%%~nxi
(
FOR /f "delims=" %%i IN ('dir /b /a-d /on') DO (
SETLOCAL enabledelayedexpansion
ECHO "%%i","!directory!"
endlocal
)
)>filelist.csv
POPD
The pathname of the directory required should be supplied as the first parameter, quoted if necessary.
Essentially, change to the directory in question, find and save the name of the leaf directory, then execute a directory scan returning the filenames. Quote both and output with a comma between. The inner setlocal is to allow at least some silly directory names.
edit 20130422-1421Z
#ECHO OFF
SETLOCAL
PUSHD "%~1"
FOR /f "delims=" %%i IN ("%cd%") DO SET directory=%%~nxi
(
FOR /f "delims=" %%i IN ('dir /b /a-d /on') DO (
SET fdate=%%~ti
SETLOCAL enabledelayedexpansion
ECHO "%%i","!directory!","!fdate:~0,10!"
endlocal
)
)>filelist.csv
POPD
Edited to show date as third element. Quotes retained - remove at will.
If date AND TIME are required, remove the SET fdate line and replace the "!fdate:~0,10!" with "%%~ti
Date and time format - to be certain, need to know the format you are using.
If you're doing a recursive directory search, filename with extension only can be obtained within your for /f loop from %%F by using %%~nxF. That's easy.
The trickier part is scraping the last folder from the path (%%~pF). There's actually an easy trick to that as well though. Use another for loop to get %%~nxI of %%~dpF. Yes, the filename.ext of a full path is the trailing directory.
This only works if the directory does not end in a trailing backslash, though. Since the result of %%~dpF does end in a trailing backslash, you can work around it simply by adding a single dot to the end. So instead of "c:\users\me\Desktop\" you get the ~nx of "c:\users\me\Desktop\." with a trailing dot.
Enough explanation. Here's how it's done.
#echo off
for /f "delims=" %%F in ('dir /s /b /o:n') do (
for %%I in ("%%~dpF.") do echo "%%~nxF","%%~nxI"
) >filelist.csv