%~1 and %1 Automatically Removing Everything after the first Space - batch-file

So I am creating a batch file to store a selected folder's path into a text file to refer to it later on using another batch script...
I created registry entries to include a right-click context menu for any folder which triggers this specific batch file.
Basically When you right click a folder and click "Send to Script" it is supposed to copy the whole path / location of the right clicked folder.
To do so I am using the following command:
SET TargetDir=%~1
I also tried using %1and I also tried using the following code with delimiters
FOR /f "delims=;" %%a in ("%~1") do (
#echo %%a
)
The problem is that CMD is automatically trimming everything after the first space and since this is a path I am copying, I want to keep all the spaces and the path as is
Ex. If I use the command on a Folder such as "C:/folder/subfolder" the copyng is done correctly But If I use the command on a Folder such as "C:/folder/sub folder" the copying is done incorrectly and will only give me "C:/folder/sub" removing all the rest found after the first space detected.
Registry Entries
[HKEY_CLASSES_ROOT\Directory\shell\send-to-script]
"MUIVerb"="Send To Script"
"SubCommands"="sendscript"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\sendscript]
#="Send To Script"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\sendscript\command]
#="C:\\scripts\\pathtotext.bat %1"
Thanks for your help

You should change your registry key [...\sendscript\command] to
#="C:\\temp\\blob.bat \"%1\""
And in your batch you should use
REM The DisableDelayedExpansion is for preserve "!" in path names
setlocal DisableDelayedExpansion
SET "TargetDir=%~1"
setlocal EnableDelayedExpansion
(
echo target is !TargetDir!
) > C:\scripts\target.log
if "reseverdFolder" == "!TargetDir!" echo This folder is reserved

The batch file is not correct registered. For example look with regedit on value of registry key:
HKEY_CLASSES_ROOT\rtffile\shell\open\command
The value is displayed as:
"%ProgramFiles%\Windows NT\Accessories\WORDPAD.EXE" "%1"
So there are two arguments which are both enclosed in double quotes:
Argument 0 is the application to run with full path, file name and file extension enclosed in double quotes as path contains a space character.
Argument 1 is the name of the RTF file referenced with %1 passed by Windows Explorer with full path, file name and file extension which of course can also contain a space or any of the characters &()[]{}^=;!'+,`~ which require also enclosing entire argument in double quotes as output by cmd.exe on running it in a command prompt window with cmd /? on last help page.
So you need in your *.reg file used to import into Windows registry:
#="\"C:\\scripts\\pathtotext.bat\" \"%1\""
This string value is displayed in registry editor as:
"C:\scripts\pathtotext.bat" "%1"
And then you can use %1 or %~1 in your batch file as explained by help of command CALL output on running in a command prompt window on execution of call /?.

SET "TargetDir=%*"
Since the parameter apparently being supplied is C:\folder\sub folder then %~1 selects only the first supplied parameter of what cmd sees as two parameters.
%* means "the whole tail"
and echoing %* should show you exactly what cmd is seeing.

Related

how to make batch file handle spaces in file names

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

Passing a string parameter as a runtime Argument

I want to open the particular path through the batch file. And I want to pass one node in path at run time. If I give input Google, I want to pass the string argument here. It will open the path
want to pass one node in path at run time . if i give input Google.i
want to pass the string argument here. it will open the path
C:\Program Files (x86)\google\Common
How can I achieve this?
My batch file:
#echo off
echo test variables
set input =
set /p input ="Choice"
echo C:\Program Files (x86)\%input%\Common
cd C:\Program Files (x86)\"%input%"\Common
pause
There are the following issues in your code:
there is a SPACE between the variable name and the = sign at the set commands, so it becomes a part of the variable name; hence the variable input remains empty/undefined;
there are quotes within the path at the cd command, which are forbidden characters there;
Here is the corrected version:
#echo off
echo test variables
set "input="
set /p "input=Choice"
echo "C:\Program Files (x86)\%input%\Common"
cd "C:\Program Files (x86)\%input%\Common"
pause
I put quotes around the path at the cd command. Although not necessary for cd, many other commands cannot handle paths containing spaces if the "" are missing.
To use the first command line argument instead of user input, remove the set commands and replace %input% by %~1. The ~ ensures that any surrounding quotes are removed. Type call /? in the command prompt for details on this.
Are you saying you want to run your batch file like this.
C:\>mybatch.bat Google
If so then your batch file just changes to this.
#echo off
echo test variables
echo C:\Program Files (x86)\%1\Common
cd C:\Program Files (x86)\%1\Common
pause

Batch Command, calling File within command

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.

About Copying Files

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!

Bat file find folder of file

So my many attempts to search for a solution have resulted in a million ways to find the folder of the bat file being executed, however what I am looking to do is find the folder for the filename being passed to the bat file.
Example:
C:\Temp\runthis.bat "C:\Blah\Ah Argh\rage.txt"
I want to get a string within that bat file that is simply "C:\Blah\Ah Argh\", alternatively I would also be able to work with getting a string of "rage.txt"
Editing to explain why: Looking to check for the filename within another txt file which is the directory listing of a ftp server to verify that a file successfully uploaded to it. Then if successful I need to move the file to a subfolder of the original folder \uploaded\ but we have many of these folders setup so I can't hard code it.
Thanks
#echo off
The file path is %~dp1
The file name is %~nx1
The parameter modifiers are the same as for FOR variables.
Type 'HELP CALL' from a command prompt for a full list of parameter modifiers.
#echo off
if %1X==X echo Syntax: %0 "path"
rem The for loop doesn't actually loop. You can split strings with it, but in
rem this case we don't. So there is only one iteration in which %%X will
rem contain the full path.
rem Pass it %1, which is the first parameter. Note the quotes, which are
rem required if you don't add quotes around the parameter and optional (but
rem still valid) when you do.
for /F "delims=|" %%X in ("%1") do (
rem FOR LOOP variables can be used with certain modifiers, preceeded by a
rem tilde. In this case I'm using d and p, which stand for drive and path,
rem effectively trimming the file name from the path.
echo %%~dpX
rem The ~n modifier selects the file name only. ~x is for extension
echo %%~nxX
)

Resources