I have the following batch file to make git diff invoke spreadsheet compare UI in windows. So I'm trying to pass the git diff's 2nd (old file) and 5th (new file) arguments to spreadsheet compare in order to make it compare the file using git diff.
So now, this batch file only successfully handles files with NO spaces in the file names, it CANNOT handle files with spaces in the file names.
What code should I add to this script to make this batch code handles file with spaces:
#ECHO OFF
set path2=%5
set path2=%path2:/=\%
ECHO %2 > tmp.txt
dir %path2% /B /S >> tmp.txt
C:/"Program Files"/"Microsoft Office"/root/vfs/ProgramFilesX86/"Microsoft Office"/Office16/DCF/SPREADSHEETCOMPARE.EXE tmp.txt
It currently throw errors like this:
Unhandled Exception: System.ArgumentException: Illegal characters in path.
at System.IO.Path.CheckInvalidPathChars(String path, Boolean checkAdditional)
at System.IO.Path.GetFileName(String path)
at ProdianceExcelCompare.Form1.StatusReady()
at ProdianceExcelCompare.Form1.Init()
at ProdianceExcelCompare.Form1..ctor(String instructionFile)
at ProdianceExcelCompare.Program.Main(String[] args)
fatal: external diff died, stopping at London comparison.xlsx
See the following answers on Stack Overflow:
How to set environment variables with spaces?
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
They explain the recommended syntax set "VariableName=variable value" to define an environment variable and the reasons recommending this syntax.
Why does ECHO command print some extra trailing space into the file?
It explains why the space character left to redirection operator > on an ECHO command line is also written into the file as trailing space and how to avoid this safely on variable text written into the file.
See also Microsoft documentation about Using command redirection operators.
On other command lines than ECHO a space left to > is usually no problem.
It is in general wrong to use multiple times " within an argument string like a file or folder path. There should be just one " at beginning and one " at end. This is explained by help of Windows command processor output on last help page on running in a command prompt window cmd /?.
The Microsoft documentation about Naming Files, Paths, and Namespaces explains that the directory separator on Windows is \ and not / and therefore / should not be used in batch files on Windows in file/folder paths.
The help output on running in a command prompt window call /? explains how the arguments of a batch file can be referenced with which modifiers.
The code rewritten according to information posted above and on the referenced pages:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "path2=%~5"
set "path2=%path2:/=\%"
>"tmp.txt" echo %2
dir "%path2%" /B /S >>"tmp.txt" 2>nul
"%ProgramFiles%\Microsoft Office\root\vfs\ProgramFilesX86\Microsoft Office\Office16\DCF\SPREADSHEETCOMPARE.EXE" "tmp.txt"
endlocal
The first line in tmp.txt contains the second argument as passed to the batch file, i.e. without or with surrounding double quotes.
The following code is necessary to write the second argument safely always without " into file tmp.txt even on second argument passed to the batch file is "Hello & welcome!":
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "path2=%~5"
set "path2=%path2:/=\%"
set "Argument2=%~2"
setlocal EnableDelayedExpansion
echo !Argument2!>"tmp.txt"
endlocal
dir "%path2%" /B /S >>"tmp.txt" 2>nul
"%ProgramFiles%\Microsoft Office\root\vfs\ProgramFilesX86\Microsoft Office\Office16\DCF\SPREADSHEETCOMPARE.EXE" "tmp.txt"
endlocal
>tmp.txt echo %~2 cannot be used as not working for something like "Hello & welcome!". Windows command processor would interpret the first string separated by normal space, horizontal tab, comma, equal sign, or no-break space (in OEM code pages) delimited string after & as command or application to execute as described by single line with multiple commands using Windows batch file.
"tmp.txt" could be written everywhere in both batch files also with just tmp.txt. But it is never wrong to enclose the complete file/folder argument string in double quotes even on not being really necessary because of the string does not contain a space or one of these characters &()[]{}^=;!'+,`~. So it is good practice to always enclose a complete file/folder argument string in double quotes. For example running a replace on both batch files searching for tmp.txt and using as replace string %TEMP%\%~n0.tmp would result in using instead of tmp.txt in current directory a temporary file with name of batch file as file name and file extension .tmp in directory for temporary files independent on what is the name of the batch file and what is the path of the directory for temporary files.
The last suggestion is reading this answer for details about the commands SETLOCAL and ENDLOCAL.
The temporary file should be also deleted finally before reaching an exit point for batch file execution.
You can use quotes as below:
It treats the string in quotes as a title of the new command window. So, you may do the following:
start "" "yourpath"
Found it in the below link :
https://ccm.net/forum/affich-16973-open-a-file-with-spaces-from-batch-file
Related
I am trying to create a list of files (about 4000) with batch file but without the extensions, some of the file names have - or _ or spaces which I would like to keep them the same, and then I am going to copy and paste the list inside Excel and run a macro that I found on this website to create individual files with different extension using the names on that list. I hope I make sense.
Here is my attempt so far:
for /f %%a in ('dir /b *.dsg') do #echo %%~na >txt1.txt
But this one just creates a list with only one name.
The batch code for this simple task is:
#echo off
del txt1.txt 2>nul
for /F "delims=" %%I in ('dir *.dsg /A-D /B 2^>nul') do echo %%~nI>>txt1.txt
The command DEL is used to delete a probably already existing file txt1.txt with redirecting the error message output to handle STDERR to device NUL to suppress it in case of the file does not exist in current directory.
Next the command DIR is executed by FOR in a separate command process. DIR lists only the names of all files matching the pattern *.dsg because of /A-D (not directory attribute) in bare format because of /B.
The error message output by DIR in case of no *.dsg file in current directory is suppressed by redirecting it to device NUL. The redirection operator > must be escaped here with caret character ^ to be interpreted as literal character when Windows command interpreter parses the FOR command line. Later on execution of DIR command line > is interpreted as redirection operator.
The list output by DIR is parsed by FOR line by line. The option delims= disables splitting up each line using spaces/tabs as delimiter. So assigned to loop variable I is always the entire line read from output of DIR.
Output by ECHO to handle STDOUT is the string left of last dot, i.e. the file name without file extension. This output is redirected to a file with appending the line to already existing file contents.
A space between %%~nI and redirection operator >> would be also output by ECHO and therefore also written as trailing space into the file.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
del /?
echo /?
for /?
Read also the Microsoft article about Using Command Redirection Operators.
#user8033911, based upon your latest comment, there seems no reason why you cannot replace the file extension with another as part of the same process.
The code below entered directly in the Command prompt window should show you, it replaces, .dsg with .new.
For /F "EOL=/Delims=/" %A In ('Where/F .:*.dsg') Do #Echo %A to "%~dpnA.new"
If you still cannot understand just comment below explaining where you are having difficulty.
I have a very simple batch script that reads a txt file and echo's it's content. The script is:
#echo off
set WORK_BASE_DIR=%~dp0
set BUILD_TXT=%WORK_BASE_DIR%Build.txt
echo %BUILD_TXT%
set PRODUCT_BUILD=0.0
for /F %%i in ("%BUILD_TXT%") do set PRODUCT_BUILD=%%i
echo %PRODUCT_BUILD%
The output of this script is:
D:\Test Dir\Project1\Build.txt \\Correct
D:\Test \\Incorrect
As you can see, the PRODUCT_BUILD is set to the path of the file and not the content of the file. The build.txt file is in the same directory and it contains just one line: 1.0.0000
If I remove the "" from the for statement, it says build.txt file not found, which is expected as the file path contains spaces.
Is there anything that I am missing?
According to the help of for /F (type for /? into a command prompt window), quotation marks denote a literal string, unless you specify the usebackq option:
for /F "usebackq" %%i in ("%BUILD_TXT%") do set "PRODUCT_BUILD=%%i"
In addition, let me recommend to use the quoted set syntax as shown above, which avoids problems with special characters and prevents invisible unintended trailing spaces to become part of the assigned value. Note that this only works if command extensions are enabled, but this is the default in every modern Windows version (based on Windows NT) anyway.
I'm building a script for Windows command line in which I try to check some filenames in a FOR loop, and then stripping off part of the filename into a variable for further use. Basically, what I want to happen is this:
List all files in a certain directory, splitting of the extension like .osm.pbf in this case.
Assign the filename to a variable.
Out the last 7 characters of the filename in another variable.
Compare this new variable to "-latest".
If the compare is true, cut a part of the variable containing the filename.
If the compare is false, take over the complete variable into another variable.
Through some trial and error and some searching online, I've arrived at this point (which still isn't doing what I want):
FOR /F "tokens=1-2 delims=." %%M IN ('DIR /b %VECTOR_WORKDIR%\*.osm.pbf') DO (
SET VECTOR_CURRENT_MAP2=%%M
ECHO !VECTOR_CURRENT_MAP2! >> %VECTOR_LOGFILE%
SET LAST_BIT_TEMP=!VECTOR_CURRENT_MAP2:~-7!
ECHO !LAST_BIT_TEMP! >> %VECTOR_LOGFILE%
SET LAST_BIT=!LAST_BIT_TEMP: =!
ECHO !LAST_BIT! >> %VECTOR_LOGFILE%
IF !LAST_BIT!=="-latest" (
SET VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2:~0,-8!
ELSE
SET VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2!
)
ECHO !VECTOR_CURRENT_MAP3! >> %VECTOR_LOGFILE%
)
This results in these lines in the log file, for the file basse-normandie-latest.osm.pbf:
basse-normandie-latest
-latest
-latest
ECHO is on.
The first echo is correct, although the filename has a trailing space. (So actually it's "basse-normandie-latest ".)
The second echo doesn't seem to take this training space into account, as it correctly gives "-latest" as the last 7 characters. This echo also has a trailing space (So actually it's "-latest ".)
The third echo is an attempt to clear the spaces from the variable (by using ": ="), but this results in another trailing space. (So actually it's "latest ".)
The final echo after the IF statement (where I try to cut the "-latest" part from the filename), results in "ECHO is on".
I have SETLOCAL enabledelayedexpansion enableextensions declared at the top of my script.
Any thoughts on how to make this work, i.e. get rid of the trailing spaces to make the comparison work?
Thanks in advance for any pointers in the right direction!
A line like
ECHO !VECTOR_CURRENT_MAP2! >> %VECTOR_LOGFILE%
results in appending the value of the environment variable VECTOR_CURRENT_MAP2 to file with file name stored in environment variable VECTOR_LOGFILE with a trailing space because there is a space before redirection operator >> which is interpreted by Windows command processor as part of the string to output by command ECHO. This space must be removed to get the file name redirected into the log file without a trailing space.
In general it is critical on redirecting a variable string into a file without a space between the variable string and the redirection operator in case of the variable string ends with a space and a number being a valid handle number like 1 or 2 or 3. There are several solutions to workaround this problem like specifying the redirection left to command ECHO, i.e.
>>%VECTOR_LOGFILE% ECHO !VECTOR_CURRENT_MAP2!
But on using delayed expansion as simply necessary here, it is safe to append the redirection at end without a space between exclamation mark and >>, i.e.
ECHO !VECTOR_CURRENT_MAP2!>> %VECTOR_LOGFILE%
The space after redirection operator is ignored by Windows command processor and therefore can be kept although many batch file programmers (like me) with good syntax highlighting don't insert a space after a redirection operator.
On comparing strings with command IF and enclosing one string in double quotes which is always a good idea, it must be made sure that the other string is also enclosed in double quotes. The command IF does not remove the double quotes before comparing the strings. The double quotes are parts of the compared strings.
The condition
IF !LAST_BIT!=="-latest"
is only true if the string assigned to environment variable LAST_BIT would be with surrounding quotes which is never the case with your batch code and therefore the condition is never true.
Correct would be:
IF "!LAST_BIT!"=="-latest"
There is no need to use command DIR to search for files with a pattern in a directory as command FOR is designed for doing exactly this task. Processing of output of command DIR is an extension of FOR available only if command extensions are enabled as by default.
The file extension is defined by Microsoft as everything after last dot in name of a file. Therefore the file extension for your files is pbf respectively .pbf and .osm belongs to the file name.
Command FOR offers several modifiers to get specific parts of a file or directory name. Those modifiers are explained in help output into console window on running in a command prompt window for /?. Help of command CALL output with call /? explains the same for processing parameters of a batch file or subroutine (batch file embedded within a batch file).
Your code with all mistakes removed:
FOR %%M IN (*.osm.pbf) DO (
SET "VECTOR_CURRENT_MAP2=%%~nM"
SET "VECTOR_CURRENT_MAP2=!VECTOR_CURRENT_MAP2:~0,-4!"
ECHO !VECTOR_CURRENT_MAP2!>>%VECTOR_LOGFILE%
SET "LAST7CHARS=!VECTOR_CURRENT_MAP2:~-7!"
ECHO !LAST7CHARS!>>%VECTOR_LOGFILE%
IF "!LAST7CHARS!" == "-latest" (
SET "VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2:~0,-7!"
) ELSE (
SET "VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2!"
)
ECHO !VECTOR_CURRENT_MAP3!>>%VECTOR_LOGFILE%
)
Easier would be using this code with using string substitution feature of command SET, i.e. search within a string case-insensitive for all occurrences of a string and replace them with another string which can be also an empty string.
FOR %%M IN (*.osm.pbf) DO (
SET "VECTOR_CURRENT_MAP2=%%~nM"
SET "VECTOR_CURRENT_MAP2=!VECTOR_CURRENT_MAP2:~0,-4!"
ECHO !VECTOR_CURRENT_MAP2!>>%VECTOR_LOGFILE%
SET "VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2:-latest=!"
ECHO !VECTOR_CURRENT_MAP3!>>%VECTOR_LOGFILE%
)
%%~nM is replaced on execution by Windows command processor by the name of the file without drive, path and file extension resulting for your example in basse-normandie-latest.osm.
The unwanted file name part .osm is removed with the next line in both batch code blocks which chops the last 4 characters from the file name string.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
for /?
if /?
set /?
Read the answer on question Why is no string output with 'echo %var%' after using 'set var = text' on command line? for an explanation why I used set "variable=value" on every line which assigns a value string to an environment variable because trailing whitespaces are critical for your task.
What am I missing?
#echo off
rem - processfiles.bat - Processes all text files in the "source" folder:
rem - Runs %executable% with each text file as parameter
rem - Move the text file to the target folder after processing
set SourceFolder=C:\Users\Chris\Desktop\Yield_Files
set TargetFolder=C:\Users\Chris\Desktop\YieldCleanFiles
set fin=default.set
if not exist "%TargetFolder%" md "%TargetFolder%"
echo Processing text files in %SourceFolder%:
for %%f in (%SourceFolder%\*.txt) do call "C:\Program Files\Yield_Editor\yieldeditor.exe/csvin="(%SourceFolder%\*.txt)"/auto="y"/hide/fin=%fin%"%%f
pause
I have to have the file name I am working on each time I call the .exe
when ran it says it cannot find the file specified, but I am not sure which one it is talking about.
The line
for %%f in (%SourceFolder%\*.txt) do call "C:\Program Files\Yield_Editor\yieldeditor.exe/csvin="(%SourceFolder%\*.txt)"/auto="y"/hide/fin=%fin%"%%f
must be written most likely
for %%f in ("%SourceFolder%\*.txt") do "C:\Program Files\Yield_Editor\yieldeditor.exe" /csvin="%SourceFolder%\*.txt" /auto=y /hide /fin=%fin% "%%~f"
or
for %%f in ("%SourceFolder%\*.txt") do "%ProgramFiles%\Yield_Editor\yieldeditor.exe" "/csvin=%SourceFolder%\*.txt" /auto=y /hide /fin=%fin% "%%~f"
which means your executable must be run with syntax
"Path to Application\Application.exe" "/First Option" /Option2 /Option3 /Option4 "File Name As Fifth Parameter"
File name of application with file extension and path must be in quotes if there is at least 1 space or another character with a special meaning which are output in a command prompt window on last help page displayed when running in command prompt window cmd /?. This is argument 0 for the application.
The first parameter/option is argument 1 for the application. It must be in quotes if the parameter string contains a space or another special character. Options not containing a space must not be quoted, but can be nevertheless also quoted.
Some applications support quoting inside an option with a variable string. An example for such a syntax would be /csvin="%SourceFolder%\*.txt".
Read the help/documentation of the application for details on using it from command line. Most Windows console applications can be executed from within a command prompt window with just /? as parameter for printing command line help to console.
It can be seen here why argument strings with spaces must be enclosed in quotes. The space is the separator for the arguments.
I want to copy some files to same destination.
Files which will be copied are listed in a text file.
So, how to read file list from text file and copy via using cmd
command?
I tried this command:
for /f "delims=" %%L in (foo.txt) do copy "%%L" new_folder
Similar question was asked in this website, I know that. When I use this command, files will be copied; but folders which include these files won't be copied.
I want to copy files with their directories.
What should I do? (Sorry for my awful English.)
You use %%L in a batchfile and %L when typing interactivly.
Your command, depending on other factors, should have a path specified for new_folder.
& seperates commands on a line.
&& executes this command only if previous command's errorlevel is 0.
|| (not used above) executes this command only if previous command's errorlevel is NOT 0
> output to a file
>> append output to a file
< input from a file
| output of one command into the input of another command
^ escapes any of the above, including itself, if needed to be passed to a program
" parameters with spaces must be enclosed in quotes
+ used with copy to concatinate files. E.G. copy file1+file2 newfile
, used with copy to indicate missing parameters. This updates the files modified date. E.G. copy /b file1,,
%variablename% a inbuilt or user set environmental variable
!variablename! a user set environmental variable expanded at execution time, turned with SelLocal EnableDelayedExpansion command
%<number> (%1) the nth command line parameter passed to a batch file. %0 is the batchfile's name.
%* (%*) the entire command line.
%<a letter> or %%<a letter> (%A or %%A) the variable in a for loop. Single % sign at command prompt and double % sign in a batch file.
.
--
Ok ,I have solved my problem via searching another cmd command:
for /f "delims=" %%i in (filelist.txt) do echo F|xcopy "-Source root folder-\%%i" "-Destination folder-\%%i" /i /z /y
In spite of the fact that I have solved my problem myself, thanks guys for your helps.
I appreciate it too much!