Batch Extract path and filename from a variable - batch-file

How can I extract path and filename from a variable?
Setlocal EnableDelayedExpansion
set file=C:\Users\l72rugschiri\Desktop\fs.cfg
I want to do that without using any function or any GOTO.
is it possible?

#ECHO OFF
SETLOCAL
set file=C:\Users\l72rugschiri\Desktop\fs.cfg
FOR %%i IN ("%file%") DO (
ECHO filedrive=%%~di
ECHO filepath=%%~pi
ECHO filename=%%~ni
ECHO fileextension=%%~xi
)
Not really sure what you mean by no "function"
Obviously, change ECHO to SET to set the variables rather thon ECHOing them...
See for documentation for a full list.
ceztko's test case (for reference)
#ECHO OFF
SETLOCAL
set file="C:\Users\ l72rugschiri\Desktop\fs.cfg"
FOR /F "delims=" %%i IN ("%file%") DO (
ECHO filedrive=%%~di
ECHO filepath=%%~pi
ECHO filename=%%~ni
ECHO fileextension=%%~xi
)
Comment : please see comments.

You can only extract path and filename from (1) a parameter of the BAT itself %1, or (2) the parameter of a CALL %1 or (3) a local FOR variable %%a.
in HELP CALL or HELP FOR you may find more detailed information:
%~1 - expands %1 removing any surrounding quotes (")
%~f1 - expands %1 to a fully qualified path name
%~d1 - expands %1 to a drive letter only
%~p1 - expands %1 to a path only
%~n1 - expands %1 to a file name only
%~x1 - expands %1 to a file extension only
%~s1 - expanded path contains short names only
%~a1 - expands %1 to file attributes
%~t1 - expands %1 to date/time of file
%~z1 - expands %1 to size of file
And then try the following:
Either pass the string to be parsed as a parameter to a CALL
call :setfile ..\Desktop\fs.cfg
echo %file% = %filepath% + %filename%
goto :eof
:setfile
set file=%~f1
set filepath=%~dp1
set filename=%~nx1
goto :eof
or the equivalent, pass the filename as a local FOR variable
for %%a in (..\Desktop\fs.cfg) do (
set file=%%~fa
set filepath=%%~dpa
set filename=%%~nxa
)
echo %file% = %filepath% + %filename%

All of this works for me:
#Echo Off
Echo Directory = %~dp0
Echo Object Name With Quotations=%0
Echo Object Name Without Quotes=%~0
Echo Bat File Drive = %~d0
Echo Full File Name = %~n0%~x0
Echo File Name Without Extension = %~n0
Echo File Extension = %~x0
Pause>Nul
Output:
Directory = D:\Users\Thejordster135\Desktop\Code\BAT\
Object Name With Quotations="D:\Users\Thejordster135\Desktop\Code\BAT\Path_V2.bat"
Object Name Without Quotes=D:\Users\Thejordster135\Desktop\Code\BAT\Path_V2.bat
Bat File Drive = D:
Full File Name = Path.bat
File Name Without Extension = Path
File Extension = .bat

if you want infos from the actual running batchfile,
try this :
#echo off
set myNameFull=%0
echo myNameFull %myNameFull%
set myNameShort=%~n0
echo myNameShort %myNameShort%
set myNameLong=%~nx0
echo myNameLong %myNameLong%
set myPath=%~dp0
echo myPath %myPath%
set myLogfileWpath=%myPath%%myNameShort%.log
echo myLogfileWpath %myLogfileWpath%
more samples?
C:> HELP CALL
%0 = parameter 0 = batchfile
%1 = parameter 1 - 1st par. passed to batchfile... so you can try that stuff (e.g. "~dp") between 1st (e.g. "%") and last (e.g. "1") also for parameters

Late answer, I know, but for me the following script is quite useful - and it answers the question too, hitting two flys with one flag ;-)
The following script expands SendTo in the file explorer's context menu:
#echo off
cls
if "%~dp1"=="" goto Install
REM change drive, then cd to path given and run shell there
%~d1
cd "%~dp1"
cmd /k
goto End
:Install
rem No arguments: Copies itself into SendTo folder
copy "%0" "%appdata%\Microsoft\Windows\SendTo\A - Open in CMD shell.cmd"
:End
If you run this script without any parameters by double-clicking on it, it will copy itself to the SendTo folder and renaming it to "A - Open in CMD shell.cmd". Afterwards it is available in the "SentTo" context menu.
Then, right-click on any file or folder in Windows explorer and select "SendTo > A - Open in CMD shell.cmd"
The script will change drive and path to the path containing the file or folder you have selected and open a command shell with that path - useful for Visual Studio Code, because then you can just type "code ." to run it in the context of your project.
How does it work?
%0 - full path of the batch script
%~d1 - the drive contained in the first argument (e.g. "C:")
%~dp1 - the path contained in the first argument
cmd /k - opens a command shell which stays open
Not used here, but %~n1 is the file name of the first argument.
I hope this is helpful for someone.

Related

Drag and Drop batch based on a java file with input and output

I tried to convert a .lc file to a .lua file, using a java app "unluac", and I did this code:
#echo on
type %1
for /r %%o in (cd %1, %CD%) do (
set o = %%~ni
)
echo %1
echo "%~dp0unluac_2021_08_29b.jar"
echo %output%
set preoutput = %1
set out = %preoutput:~-3%
java -jar "%~dp0unluac_2021_08_29b.jar" "%1" > "%1%.lua"
pause
I let the ECHO on ON to get the logs and know what work and what doesn't work.
The file is converted, but or it take "input.lc.lua" or it just out ".lua".
I tried to substring the characters in the filename (the .lc) but it didn't work and returned an empty string.
Your question is very unclear and your code makes no sense.
You must do yourself a favor and open cmd then run set /? and for /? to see all the help you need.
Anyway, you seemingly just need to strip the extension. there is an expansion model you can use i.e %~dpnx1 Those are drive, path. name and extension. Therefore you should be able to run something similar to:
start "" "C:\<Path to Java>\java.exe" -jar "%~dp0unluac_2021_08_29b.jar" "%~1" > "%~n1.lua"

If statement in batch script isn't working?

I have a batch script which when given the input "edit", should then echo "hello" as a sort of debug and open the batch scripts file in notepad. However for some inexplicable reason the script will not respond to the if statement no matter what. How do I get it to respond to the "edit" input?
REM #ECHO OFF
cd/
cd projects\py_test
ECHO Use this batch script to lauch Python modules living in "C:\Projects\py_test\" ONLY.
ECHO.
SET /P name="Type file name with file extension .py to start or type EDIT to edit this .bat: "
REM #ECHO OFF
cmd /k IF %name%==edit GOTO EDIT
REM IF EXIST %name% py %name%
REM IF NOT EXIST %name% echo [101mERROR: The requested file could not be found. Make sure the file exists in "C:\Projects\py_test\" and that the filename includes the ".py" extension.[0m
#ECHO OFF
:EDIT
ECHO HELLO
notepad projects-py_test-dot_start.bat`
Firstly, why all the REM #ECHO OFFs? It looks ugly, especially when they are all caps.
Then, you want to run cmd /k for an if statement for no real reason? With the variable name you need to preferbly enclose the if statement variables in double quotes to eliminate possible whitespace:
#echo off
cd /d "C:\projects\py_test"
echo Use this batch script to lauch Python modules living in "C:\Projects\py_test\" ONLY.
echo/
set /p name="Type file name with file extension .py to start or type EDIT to edit this .bat: "
if defined name set "name=%name:"=%"
if /i "%name%"=="edit" goto edit
goto :EOF
:edit
echo hello
notepad echo "%~f0"
but by guessing that you simply want to launch a python script if it exists, else edit itself, then I would instead do this version without the labels. It simply checks if the name typed exists (hoping the user typed the full script with extension) else, we add the extension test in case the user typed only the name and not extension.:
#echo off
cd /d "C:\projects\py_test"
echo Use this batch script to lauch Python modules living in "C:\Projects\py_test\" ONLY.
echo/
set /p name="Type file name with file extension .py to start or type EDIT to edit this .bat: "
if defined name set "name=%name:"=%"
if /i "%name%"=="edit" notepad "%~f0"
if exist "%name%" (
python "%name%"
) else (
if exist "%name%.py" (
python "%name%.py"
) else (
echo "%name%" does not exist
)
)

Batch %1 get path with whitespace

I have set up a batch file to be default to open .txt files. In an earlier question I found out that %1 gives me the path of the file which was actually calling the batch file. The Problem is: if the file name contains white space, it gets interpreted as multiple parameters.
Example:
opening file "C:\Users\Desktop\space true.txt"
%1 gives:"C:\Users\Desktop\space" and then %2 gives: "true.txt"
How could I get just the full file path with the name and white space without trying to do a loop to attempt to get the full path by combining %1%2%3%4...
UPDATE-----------------------
Sorry there was a miss communication. The code below is working. The trick was to put "%*" instead of "%1"
here the code:
#echo on
set var= "%*"
c:
cd "C:\Users\MyText Editor"
start javaw -jar "MyTextEditor.jar"%var%
pause
I do the whole changing the path, because the file which I double click and the the the batch file are in different directories. I had to change it to this.
UPDATE 2 --------------------------
The solution which worked best for me was from this fine gentlemen dbenham.
#echo off
pushd "C:\Users\MyText Editor"
start javaw -jar "MyTextEditor.jar" %*
The only complain I have is, that there is a case, where %* does not return the path with quotes. So I am searching for a final solution. Something like this "%~*" But this doesn't work.
Thanks in advance
The following is not quite correct - I thought the file associations would put quotes around the file name like drag and drop does. But I was mistaken
This line is the source of your problem:
set var= "%*"
When files are dragged onto your batch script, or if a text file is double clicked, any file name(s) containing space will automatically be enclosed within quotes.
When you add your own additional quotes, it defeats the purpose of the quotes - the space is no longer quoted.
For example, a string like "name with space.txt" is treated as a single arg, but with added quotes, ""name with space.txt"" becomes three arguments.
There is no need for your var variable. You can use %* directly in your START command.
#echo on
pushd "C:\Users\MyText Editor"
start javaw -jar "MyTextEditor.jar" %*
pause
I'm not sure the above works properly if multiple files are passed. I suspect you may want the following:
#echo on
pushd "C:\Users\MyText Editor"
for %%F in (%*) do start javaw -jar "MyTextEditor.jar" %%F
pause
There is one potential problem. Windows has a bug in that file names containing & are not automatically quoted as they should. See "Droplet" batch script - filenames containing ampersands for more info.
EDIT - The following should work
OK, I did some tests and I believe your best bet is to modify the command associated with .txt files.
I tested association changes via the command line. This must be done via an elevated command prompt with admin rights. On my machine I go to the Start menu, click on "All Programs", click on "Accessories" folder, right click "Command Prompt", and select "Run as administrator", then click "Yes" to allow the program to make changes to the system.
The following command will show which file type needs to be modified
assoc .txt
On my machine it reports .txt=txtfile, so txtfile is what must be modified using FTYPE.
I believe the following should work for you:
ftype txtfile="C:\pathToYourScrpt\yourScript.bat" "%1"
Obviously you would need to fix the path to your batch script :-)
Once you have made the change, the filename will automatically be quoted every time your script is invoked via a file association.
Your batch script can then look like the following, and it should work no matter how it is invoked (excepting drag and drop with file name containing & but no space):
#echo off
pushd "C:\Users\MyText Editor"
for %%F in (%*) do start javaw -jar "MyTextEditor.jar" %%F
It seems to me you should be able to eliminate the batch script and configure FTYPE TXTFILE to open your java editor directly. I should think something like the following:
ftype txtfile="c:\pathToJava\javaw.exe" -jar "C:\Users\MyText Editor\MyTextEditor.jar" "%1"
When calling your batch file, you must enclose your parameter in quotes if there is spaces in it.
E.g.: Batch.cmd "C:\Users\Desktop\space true.txt"
Eric
%*
Here's a list of characters.
& 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.
Your problem is really that the syntax of your set command is wrong. In a batch
file, a set command looks like this:
set "var=%1"
That will give you your variable exactly as received. If the user quoted it,
then the variable's value will have quotes around it. To remove the quotes,
you'd put a ~ in front of the number:
set "var=%~1"
Notice how the quotes go around the entire assignment, and not just around the
value you are assigning. It is not set var="%1".
If you use set var= "%*", you haven't really fixed the fundamental problem
that your syntax is wrong. Plus, often you really do want %1 and not the
entire command line.
Here is an example script to test various quoting behaviors:
#echo off
set var="%*"
echo 1. var="%%*" --^> [%var%] (wrong)
set "var=%*"
echo 2. "var=%%*" --^> [%var%]
set "var=%1"
echo 3. "var=%%1" --^> [%var%]
set "var=%~1"
echo 4. "var=%%~1" --^> [%var%]
set "var=%~2"
echo 5. "var=%%~2" --^> [%var%]
set "var=%~3"
echo 6. "var=%%~3" --^> [%var%]
And here is the output of that script. Note how arg1, arg2, and arg3 are all
quoted:
C:\batch> all_args.cmd "arg 1" "this is arg 2" "arg 3"
1. var="%*" --> [""arg 1" "this is arg 2" "arg 3""] (wrong)
2. "var=%*" --> ["arg 1" "this is arg 2" "arg 3"]
3. "var=%1" --> ["arg 1"]
4. "var=%~1" --> [arg 1]
5. "var=%~2" --> [this is arg 2]
6. "var=%~3" --> [arg 3]
You can see that numbers 4, 5, and 6 correctly pulled out their quoted arguments
and saved the value into var. You typically want to save the argument without quotes, and then quote it when you use it in your script. In other words, your script should look like this:
#echo on
set "var=%~1"
c:
cd "C:\Users\MyText Editor"
start javaw -jar "MyTextEditor.jar" "%var%"
pause
#echo on
set var= "%*"
c:
cd "C:\Users\MyText Editor"
start javaw -jar "MyTextEditor.jar"%var%
pause
Becomes removing redundant commands
start "" javaw -jar "C:\Users\MyText Editor\MyTextEditor.jar" "%*"
pause
Echo is already on unless turned off by you.
We don't put things into variables for no reason, and it's already in %*. It just makes convoluted code and removes meaning from the name of the variable.
When programming (unlike typing) we don't change paths (and cd /d C:\Users\MyText Editor does drive and folder anyway).
We specify full path on the command line. This makes your meaning quite clear.
The main problem was there was no space between .jar and %var% and start command the first quotes on the line are assumed to the CMD's window title. I would code the path to javaw and not use start. Start is asking the Windows' graphical shell to start the file, not CMD.
Here's a batch file that starts vbs files. I don't specify path to cscript as it's a Windows' command.
It's complexity is to make use fairly idiot proof and easy for others.
#echo off
Rem Make sure filter.vbs exists
set filter=
set filterpath=
Call :FindFilter filter.vbs
Rem Add filter.bat to the path if not in there, setx fails if it's already there
setx path %~dp0;%path% 1>nul 2>nul
Rem Test for some command line parameters
If not "%1"=="" goto main
echo.
echo -------------------------------------------------------------------------------
echo.
echo Filter.bat
echo ==========
echo.
echo The Filter program is a vbs file for searching, replacing, extracting, and
echo trimming console output and text files.
echo.
echo Filter.bat makes Filter.vbs easily usable from the command line. It
echo controls unicode/ansi support and debugging.
echo.
echo Type Filter Help or Filter HTMLHelp for more information.
echo.
cscript //nologo "%filter%" menu
Goto :EOF
:Main
echo %date% %time% %~n0 %* >>"%~dp0\FilterHistory.txt"
rem echo Batch file ran
rem echo %*
Rem /ud Unicode and Debug
If %1==/ud FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //u //x %%j&Goto :EOF
Rem /u Unicode
If %1==/u FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //u %%j&Goto :EOF
Rem /d Ansi Debug
If %1==/d FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //x %%j&Goto :EOF
Rem -ud Unicode and Debug
If %1==-ud FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //u //x %%j&Goto :EOF
Rem /u Unicode
If %1==-u FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //u %%j&Goto :EOF
Rem -d Ansi Debug
If %1==-d FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //x %%j&Goto :EOF
Rem ANSI
cscript "%filter%
" //nologo %*&Goto :EOF
Goto :EOF
:FindFilter
If Exist "%~dpn0.vbs" set filter=%~dpn0.vbs&set filterpath=%~dp0&goto :EOF
echo find filter 1
If Not "%~dpnx$PATH:1" == "" set filter=%~dpnx1&set filterpath=%~dp1&goto :EOF
echo find filter 2
If Exist "%temp%\filter.vbs" set filter=%temp%\filter.vbs&set filterpath=%temp%&goto :EOF
copy "%~dpnx0" "%~dpn0.bak"
if not errorlevel 1 (
echo creating "%~dpn0.vbs"
goto :EOF
)
copy "%~dpnx0" "%temp%\filter.bak"
echo Error %errorlevel%
if not errorlevel 1 (
echo creating "%temp%\filter.bak"
Goto :EOF
)
Goto :EOF

Command for getting the file size

Could anybody please tell me a shell command for Windows 7 which would take a file path as argument and return the size of that file - Something like:
fileSize.cmd file.txt
...which will give me 1KB.
One question in SO noted the command echo %~z1, but for this, I have to write a separate batch file and use this command in it. I was thinking of modifying my existing bat file and incorporate this command somehow. My batch file looks like this:
p4 diff //sources/j2cs/output.txt >> diff_out.txt
I have to add above command in the existing bat file to find the file size of diff_out.txt.
You don't need an extra batch file, you could move your filename into %1 with a call to a function or you can use a FOR loop.
call :getFilesize diff_out.txt
echo %fileSize%
exit /b
:getFilesize
set filesize=%~z1
exit /b
Or
for %%A in (diff_out.txt) do set fileSize=%%~zA
another variant:
#echo off
set file=c:\bookmarks.html
%1 %0 :: %file%
set len=%~z2
echo %len%
pause
or with wmic:
D:\>set wql="drive='g:' and filename='function2' and extension='txt'"
D:\>wmic path cim_datafile where %wql% get name,filesize
FileSize Name
621 g:\function2.txt
D:\>
or:
set file=G:\function2.txt
echo set len=%%~z1 >_tmp.bat
call _tmp.bat %file% && del _tmp.bat
echo %len%

Directory Names in Batch

How can I store a directory name in a variable inside batch file??
set dirname=c:/some/folder
echo %dirname%
REM retrieve the last letter of the folder
REM and save it in another variable
set lastLetter=%dirname:~-1%
echo %lastLetter%
To return the directory where the batch file is stored use
%~dp0
%0 is the full path of the batch file,
set src= %~dp0
echo %src%
I've used this one when I expect certain files relative to my batch file.
Without more precisions it's difficult to help you...
Maybe you want the current directory?
set name=%CD%
echo %name%
Use the set command.
Example:
rem Assign the folder "C:\Folder1\Folder2" to the variable "MySavedFolder"
set MySavedFolder=C:\Folder1\Folder2
rem Run the program "MyProgram.exe" that is located in Folder2
%MySavedFolder%\MyProgram.exe
rem Run the program "My Second Program.exe" that is located in Folder 2 (note spaces in filename)
"%MySavedFolder%\My Second Program.exe"
rem Quotes are required to stop the spaces from being command-line delimiters, but the command interpreter (cmd.exe) will still substitute the value of the variable.
To remove the variable, assign nothing to the name:
set MySavedFolder=
Since you are inside a batch file, I suggest surrounding your variable usage with setlocal and endlocal at the end of the file; this makes your environment variables local to the batch file and doesn't pollute the global environment namespace.
To allow a script to determine its parent folder directory name:
#echo off
::setlocal enableextensions,enabledelayedexpansion
SET CDIR=%~p0
SET CDIR=%CDIR:\= %
FOR %%a IN (%CDIR%) DO (
SET CNAME=%%a
)
echo %CDIR%
echo %CNAME%
pause
Or, better yet:
#echo off
::setlocal enableextensions,enabledelayedexpansion
SET CDIR=%~p0
SET CDIR=%CDIR:~1,-1%
SET CDIR=%CDIR:\=,%
SET CDIR=%CDIR: =_%
FOR %%a IN (%CDIR%) DO SET "CNAME=%%a"
echo %CDIR%
SET CNAME=%CNAME:_= %
echo %CNAME%
pause

Resources