This is a popular subject on the Web but I can't find a simple way to do a find-and-replace inside a CSV file. My CSV file looks like this:
"0.219530613504834,43.7737904197643,PR RUE D'ARTOIS"
"0.522235882011867,41.7681203998576,PR DE LA FOSSE AU ROI"
"0.039404145384227,44.7565229712732,PR DES PETITS PRES"
I need to remove double quotes at the beginning and end of each line.
I tried the following script:
setlocal enabledelayedexpansion
for /f "tokens=*" %%a in (D:/data.csv) do (
set temp=%%a
set temp=%temp:^"=%
)
My logic is to store each line in %%a and to replace the double quotes by nothing.
I escape the double quote with ^.
This script is doing nothing. Could you help?
There is a much simpler solution that avoids delayed expansion altogther - The ~ modifier strips enclosing quotes from FOR variable content.
for /f "delims=" %%a in (D:/data.csv) do echo %%~a
Your attempt has several issues:
You need to use delayed expansion (use ! instead of %). Without delayed expansion, the variable gets expanded before the loop is entered.
It's more reliable to use "delims=" than "tokens=*". With "tokens=*" each line is still tokenized, and then all tokens are concatenated separated by a space. But the tokens may have originally been separated by a ;. So if you had "one;two" in the input you'd get "one two" in the output.
You don't need to escape the ".
You need to print temp, not just modify it without using the new value.
setlocal enabledelayedexpansion
for /f "delims=" %%a in (D:/data.csv) do (
set temp=%%a
echo !temp:"=!
)
Related
I do need a batch script who will remove all columns in a csv, except column 1,2 and 5
My Code:
(for /f "tokens=1,2,5 delims=;" %%i in (Input.csv) do echo %%i,%%j,%%k) > Output.csv
Input CSV
1;2;3;4;5;6;7;8;9;10
10160;"Some Name";"Something:0.8";;5;;;;;XY
Expected Output:
1;2;5
10160;"Some Name";5
Real Output
1,2,5
10160,"Some Name",XY
Does anyone have any idea why it keeps the tenth column in the second line instead of the fifth?
SETLOCAL ENABLEDELAYEDEXPANSION
(FOR /f "delims=" %%b IN (Input.csv) DO SET "line=%%b"&SET "line=!line:;;=; ;!"&for /f "tokens=1,2,5 delims=;" %%i in ("!line:;;=; ;!") do echo %%i,%%j,%%k)
The problem is that a sequence of delimiters is considered as a single delimiter, so you need to change each delimiter pair so that it contains a string, and repeat the operation for any remaining delimiter-pairs.
Obviously, you would need to take action to take care of a reported field that now contains a single space, and this will alter any quoted field that contains ;;
Note also that any data containing ! or % is likely to be corrupted and certain other symbols (such as &) may also yield unexpected results. If the data is restricted to alphamerics, spaces, commas, etc. it should be fine.
Currently i have a csv export with the following output
number;sentence;text;text;text;text;text;text;18.05.2012;time;text;text;number
number;sentence;text;text;text;text;text;text;18.05.2012;time;text;text;number
number;sentence;text;text;text;text;text;text;#;time;text;text;number
number;sentence;text;text;text;text;text;text;#;time;text;text;number
Notice that it sometimes happens that a date is not present, instead "#" has been inserted. The # is also present in other parts of the CSV file, however this shouldn't be impacted. Which currently happens
#echo off
setlocal enableextensions enabledelayedexpansion
(for /f "skip=4 tokens=1-9* delims=," %%f in (input.csv) do if not "%%f"=="" (
set "line=%%f"
set "line=!line:#"=!"
echo(!line!
)) > output.csv
endlocal
Any pointers where i go wrong?
I guess, you didn't quite understand the "tokens" thing. The first token is set to the given variable (%%a), the next tokens are assigned to the (alphabetically) following variables (%%b, %%c, ...). You need to change the ninth token (%%i), so you have to retrieve tokens 1 to 9 and * for "the rest". Also your delimiter was wrong (your text file has ;, so you need delims=;)
#echo off
setlocal enableextensions enabledelayedexpansion
(for /f "skip=4 tokens=1-9* delims=;" %%a in (input.csv) do (
if "%%i"=="#" (set "data=") else (set "data=%%i")
echo(%%a;%%b;%%c;%%d;%%e;%%f;%%g;%%h;!data!;%%j
)) > output.csv
endlocal
(Of course you also could start with %%f, but then your ninth token is %%n - it's easier to read when you start with a)
Keep in mind, consecutive delimiters are treated as one. So if you have empty fields (...;text;;text;...) your tokenization goes wild.
I run the batch script on below on a csv file.
#echo off
set "filename=test.csv"
for /f "USEBACKQtokens=*" %%A in ("%filename%") do (
call :myecho "%%A"
)
pause
:myecho
echo %1
GOTO :eof
A typical line in the csv file looks like this:
Text and some more 2/11/2015,A234,Mr. Example Guy,18217.01,"$20,729.89","$4,111.06","$4,453.08"
The echo will actually result in the following output:
Text and some more 2/11/2015,A234,Mr. Example Guy,18217.01,"$20,
Somehow it cuts off at the comma, after the first quotation mark. I don't understand why. Could someone explain, and tell me how I could print the entire line there? Note that if I print directly in the for loop it prints the entire line.
The following line
call :myecho "%%A"
is expanded to
call :myecho "Text and some more 2/11/2015,A234,Mr. Example Guy,18217.01,"$20,729.89","$4,111.06","$4,453.08""
Arguments to CALLed subroutines are delimited by any of <space>, ,, ;, <tab>, =, or <0x255>. Delimiters within quotes are ignored. The commas in $20,729.89 are quoted in the original CSV, but they are not quoted in your CALL because you added your own enclosing quotes. So argument %1 ends at the first unquoted comma in the dollar amount.
If you want to pass a string containing quotes and delimiters to a subroutine, then you should pass them by reference via an environment variable. You should use delayed expansion to expand the variable so that all characters are protected. But delayed expansion should be off within the FOR loop so that ! values are not corrupted when the FOR loop variable is expanded.
#echo off
setlocal disableDelayedExpansion
set "filename=test.csv"
for /f "USEBACKQtokens=*" %%A in ("%filename%") do (
set "var=%%A"
call :myecho var
)
pause
exit /b
:myecho
setlocal enableDelayedExpansion
echo !%1!
exit /b
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