Batch Script – Delete Characters in a String till delimiter - batch-file

I am desperately looking for a solution to the following problem:
I have a batch file that reads a path from a txt file and saves it as a string. For example: pathname=C:\User\Software\v1.1\Test\abcdefg
Now I just want to get the path and delete everything from the last "\". So a folder above the final folder in the path:
result=C:\User\Software\v1.1\Test
I have a hard time with batch scripts, I hope you can help me.
set result=%pathname:*\=%
This deletes the chars befor the first "\": User\Software\v1.1\Test\abcdefg
Is there a way to give back every char before the last "\" like: C:\User\Software\v1.1\Test
The paths will differ in length everytime.

#ECHO OFF
SETLOCAL
SET "pathname=C:\User\Software\v1.1\Test\abcdefg"
for %%e in ("%pathname%") do set "result=%%~dpe"
SET "result=%result:~0,-1%"
ECHO +%result%+
GOTO :eof
Treating the pathname as though it was a filename.
The + at either end of the report shows there are no extra spaces in the result.

Related

extract second last Substring in bat file

I am trying to get the substring which lies between the last & second last fullstop (.) in a filename using the batch file, filename can have any number of fullstops. The file name will look like as follows, in this particular example output should be '8'.
filename: a_b_c_d_e.1.2.3.4.5.6.7.8.9
I tried the below part, but it always outputs the string after the first fullstop i.e 1.2.3.4.5.6.7.8.9 instead of '8'.
set "string=a_b_c_d_e.1.2.3.4.5.6.7.8.9"
#echo %string:*.=%
pause
Any working suggestions can be helpful.
You could use the file modifier syntax.
Replace all dots with backslashes and then take the parent directory by appending \..
#echo off
set "string=a_b_c_d_e.1.2.3.4.5.6.7.8.9"
for /F "delims=" %%X in ("%string:.=\%\..") do echo %%~nX

Use batch file to check if files with specific extension are in a specific folder

In a batch file, I need to get a path from the user, remove the trailing backslash if they included it, and then check if any files with the .sql extension are in the folder that they specified. If not, I want to return them to the variable entry section.
Here's what I have:
REM Get the folder paths from the user
:setfolderpaths
set /p SCRIPTFOLDER="D:\Mark\Centriq Extraction Projects\"
set /p OUTPUTFOLDER="D:\Mark\Centriq Extraction Projects\"
REM View what the user entered (testing only)
echo %SCRIPTFOLDER%
echo %OUTPUTFOLDER%
REM pause here to check the user entry (testing only)
#pause
REM Remove trailing slashes from the folder path if they exist
if %SCRIPTFOLDER:~-1%==\ set SCRIPTFOLDER=%SCRIPTFOLDER:~0,-1%
if %OUTPUTFOLDER:~-1%==\ set OUTPUTFOLDER=%OUTPUTFOLDER:~0,-1%
REM If the folder the user entered doesn't exist, go back to the folder entry section
if not exist %SCRIPTFOLDER% + "\*.sql" (
goto setfolderpaths
)
However, when I run the file, after I press a key to continue at the pause, the cmd window closes immediately. I've checked that the lines removing the backslash work, so the problem seems to be in my if not exist check.
EDIT
Apparently, I had some code in my sample that was confusing what I am trying to figure out. I've added comments to explain what I'm doing in each part. I just need to figure out why my check for.sql files in the user-specified folder isn't working.
UPDATE
Okay, I cleaned up my quoting issues per #LotPings' suggestions.
So, when I put an echo right before the if check:
echo %SCRIPTFOLDER%
#pause
That's displaying a valid path that I know does have sql files in it. So this code isn't working:
if not exist "%SCRIPTFOLDER%\*.sql" (
goto setfolderpaths
)
When I hit a key to continue at the pause the cmd window closes.
This are all quoting issues.
If the double quote is the last char (as is the case above) and you remove it,
the string has only a leading d'quote and still a trailing backslash.
Better quote always like this:
:setfolderpaths
set "SCRIPTFOLDER=D:\Mark\Centriq Extraction Projects\"
set "OUTPUTFOLDER=D:\Mark\Centriq Extraction Projects\"
echo %SCRIPTFOLDER%
echo %OUTPUTFOLDER%
#pause
REM Remove trailing slashes from the folder path if they exist
if "%SCRIPTFOLDER:~-1%"=="\" set "SCRIPTFOLDER=%SCRIPTFOLDER:~0,-1%"
if "%OUTPUTFOLDER:~-1%"=="\" set "OUTPUTFOLDER=%OUTPUTFOLDER:~0,-1%"
if not exist "%SCRIPTFOLDER%\*.sql" (
goto setfolderpaths
)
Also there is no string concatenation with + you used in your if.
Read the answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? and you know what is wrong on first two SET command lines.
Original question: The folder paths are assigned to the environment variables with both double quotes and so the last character of both environment variable values is " and not the backslash as expected by you.
Edited question: The two folder paths are displayed as prompt text.
The wrong position of first " on SET command lines is responsible for syntax errors on remaining lines as well as + on IF condition line. Windows command processor does not support string concatenations using an operator +. The strings to concatenate must be just written concatenated in the batch file.
Here is a batch file which prompts the user for both paths and runs some checks as the user has the freedom to enter nothing or strings which could do something really bad without appropriate checks in right sequence without using delayed environment variable expansion. The command lines are modified by Windows command processor before execution by each %ScriptFolder% and %OutputFolder% reference. It never really matters what is written in batch file. It matters how each command line or an entire command block looks like after parsing by Windows command processor cmd.exe on execution of batch script.
#echo off
:GetScriptFolderPath
set "ScriptFolder="
set /P "ScriptFolder=Enter script folder path: "
rem Has the user not entered any string?
if not defined ScriptFolder goto GetScriptFolderPath
rem Remove all double quotes from entered string.
set "ScriptFolder=%ScriptFolder:"=%"
rem Has the user entered a string consisting only of double quotes?
if not defined ScriptFolder goto GetScriptFolderPath
rem Remove a backslash at end of user entered string.
if "%ScriptFolder:~-1%" == "\" set "ScriptFolder=%ScriptFolder:~0,-1%"
rem Has the user entered just a backslash (with one or more double quotes)?
if not defined ScriptFolder goto GetScriptFolderPath
rem Is the user entered string really a path to a directory
rem which really exists and contains at least one *.sql file?
if not exist "%ScriptFolder%\*.sql" goto GetScriptFolderPath
:GetOutputFolderPath
set "OutputFolder="
set /P "OutputFolder=Enter output folder path: "
if not defined OutputFolder goto GetOutputFolderPath
set "OutputFolder=%OutputFolder:"=%"
if not defined OutputFolder goto GetOutputFolderPath
if "%OutputFolder:~-1%" == "\" set "OutputFolder=%OutputFolder:~0,-1%"
if not defined OutputFolder goto GetOutputFolderPath
rem Is the user entered string really a path to an existing directory?
if not exist "%OutputFolder%\" goto GetOutputFolderPath
Note: The batch file user can also drag & drop a folder path for example from Windows Explorer into the console window to enter the path and needs to press next only RETURN or ENTER to complete the input prompt.
It is also possible to use set "ScriptFolder=D:\Mark\Centriq Extraction Project" instead of just set "ScriptFolder=" to define a non empty default on which the user has just to press RETURN or ENTER for using it. A default folder path can be also set for the output folder.

Use Dos commands to copy file and preserve date in file name

I'm having trouble trying to copy and rename a file using only dos commands. I have a file of the format myfile20130218 and want to copy and rename it to some_other_file_20130218.
I know I can use copy source dest but I'm having trouble with how to isolate the date and preserve it. I cannot guarantee that he date will be today's date so that is ruled out, the source file will always be the same name.
I can run either a series of commands or a batch script, but thing that that I am currently having trouble with, is after I find a match that I need to copy, using myfile????????, how can I now get those file names to pull the dates off them?
EDIT: for clarification I will be looking at files in a known directory, as above, I will know the format of the file name, and will only be checking a specific directory for it. The process that checks the directory is a ConnectDirect file watcher, so when a file is found matching myfile20130218 I can fire off some commands, but don't know how to check the directory and get the name of the file present.
Something like this should work:
%oldname:~-8% extracts the last 8 characters from %oldname% which are then appended to the new filename.
Update: If you can identify the file with an external program and then call the batch script with the file name
copyfile.cmd C:\path\to\myfile20130218
you could do something like this:
set oldname=%~nx1
set newname=%~dp1some_other_file_%oldname:~-8%
copy "%~f1" "%newname%"
Update 2: If you know folder and the format you could call the script with the folder
copyfile.cmd C:\folder
and do something like this:
#echo off
setlocal EnableDelayedExpansion
for /f %%f in (
'dir /b "%~f1" ^| findstr /r "myfile[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$"'
) do (
set oldname=%~f1\%%f
set newname=%~f1\my_other_name_!oldname:~-8!
copy "!oldname!" "!newname!"
)
endlocal
Edit: Script breakdown.
setlocal EnableDelayedExpansion enables variable expansion inside loops and conditionals.
for /f %%f in ('...') executes the command between the single quotes and then loops over the output of that command.
dir /b "%~f1" lists the content of the given directory (%~f1 expands to the full path of the first argument passed to the script) in simple mode (no header, no summary).
findstr /r "myfile[0-9]...[0-9]$" filters the input for strings that end with the substring "myfile" followed by 8 digits. The circumflex before the pipe (^|) escapes the pipe, because otherwise it would take precedence over the for command, which would effectively split the for command in half, resulting in an invalid command-line.
set oldname=%~f1\%%f assign the full path to a matching file to the variable oldname.
set newname=%~f1\my_other_name_!oldname:~-8! assign the full path to the new filename ("my_other_name_" followed by the trailing 8 digits from oldname) to the variable newname.
copy "!oldname!" "!newname!" I don't need to explain this, do I?

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
)

DOS- keeping portion of directory structure during xcopy?

I am a bit new to DOS batch files, and I am having a hard time wrapping my head around ways to solve my problem.
What I need to do: I have a large, nested source folder structure, let's say it lives here:
C:\dir1\dir2\dir3\file.txt
And I have a mirrored destination structure, although a portion of the root is different:
x:\dirA\dirB\dir1\dir2\dir3\file.txt
My current batch copies all files in the source structure to a destination folder, keeping the folder structure, which is what I want.
The problem:
The intention of my script is to drag a folder from the source structure above onto the bat file, and have it copy the files to the destination. What I want to do, is to allow the user to drag a folder from source dir, let's say /dir2 and all of its subfolders/files onto the batch file, and have it copy the contents over to the SAME spot in the destination structure...
So in this example, the batch file should copy everything in and below:
C:\dir1\dir2\
into
x:\dirA\dirB\dir1\dir2\.
Fortunately (I think) my destination folder structure won't be changing, although the source might be in a different location on each machine. So, if there is a clever way to detect where in the source tree I am, and then replace a portion of the destination path... ???
Here's my simple script so far:
#echo off
set /p FILETYPE="What file type do you want to copy? (For example use txt, max, f3d, or * to copy all files.)"
xcopy %1\*.%FILETYPE% c:\output /s
pause
Thanks so much for any help you guys can give! :)
Ken
UPDATE: Adding updated code sample here because I cannot get my comment to format or allow me enough chars. The stuff below may not be completely correct, I am just trying my best to be clear. I have figured out more since I posted this, basically I need to figur out how (or if possible) to use a string after delims, it only seems to check for each character...
#echo off
rem user drag folder onto .bat (left click, move folder using mouse onto .bat icon)
rem %1 in ex is C:\random_folder\another_folder\proj1\area1\scene23
set destRoot=X:\companyname\allprojects\proj1
set rootDir=proj1
rem assume %1 is folder dragged onto .bat file
for /f "tokens=2* delims=<foldername???>" %%a in ("%1") do (
set part1=%%a
set chunk=%%b
)
set finalDest=destRoot+chunk
xcopy %1\* %finalDest% /E /EXCLUDE:exclusions.txt
pause
I am hoping to create this: "X:\companyname\allprojects\proj1\area1\scene23"
Is the x:\dirA\dirB\ part of the destination folder known? If so, the solution is easy:
#echo off
rem Get current directory, ie: "C:\dir1\dir2"
set curDir=%cd%
rem Eliminate the disk drive, ie: "\dir1\dir2"
set curDir=%curDir:~2%
rem Copy to right destination, ie: "x:\dirA\dirB\dir1\dir2"
xcopy *.%FILETYPE% "x:\dirA\dirB%curDir%"
I hope it helps...
EDIT: Clarification to new comments requested
Ok. There is a source folder and a destination folder. The program above assume that the current folder for the program is source folder, but this may be provided as a parameter if needed. The program achieve the following copy processes:
From source folder -> To destination folder
C:\dir1\dir2 -> x:\dirA\dirB\dir1\dir2
C:\dir1\dir2\dir3 -> x:\dirA\dirB\dir1\dir2\dir3
C:\dir1\dir2\dir3\what\ever -> x:\dirA\dirB\dir1\dir2\dir3\what\ever
C:\XYZ -> x:\dirA\dirB\XYZ
If this is not what you want then explain it as concise as possible (use "files", "folder", "part of name" terms, not "I like", "what if", etc), and include three or four examples.
Also, note that for me drag a folder mean a drag&drop operation taking the source folder pressing the right button of the mouse and leave it over the icon of the Batch file. If you are NOT refering to this operation, please do NOT use "drag" term; use "copy" instead (please also clarify this point).
EDIT: Solution to new requirements
OK! You have not explained correctly before your last example! This problem is just about matching two names: last part of first name must match the same part in second name, and combine first name and the rest of second name. Right?:
First name: X:\companyname\allprojects\proj1
Second name: C:\random_folder\another_folder\proj1\area1\scene23
Result: X:\companyname\allprojects\proj1\area1\scene23
This is the solution:
#echo off
setlocal EnableDelayedExpansion
rem user drag folder onto .bat (left click, move folder using mouse onto .bat icon)
rem %1 in ex is C:\random_folder\another_folder\proj1\area1\scene23
set sourceFolder=%~1
set destRoot=X:\companyname\allprojects\proj1
rem Get last part of First name (destRoot) ie: lastPart=proj1
for %%a in (%destRoot%) do set lastPart=%%~Na
rem Delete from beginning of second name until that part, ie: result=\area1\scene23
set result=!sourceFolder:*%lastPart%=!
rem And insert the First name before the rest
set result=%destRoot%%result%
Or, combining the three steps in just one line:
#echo off
rem user drag folder onto .bat (left click, move folder using mouse onto .bat icon)
rem %1 in ex is C:\random_folder\another_folder\proj1\area1\scene23
set sourceFolder=%~1
set destRoot=X:\companyname\allprojects\proj1
for %%a in (%destRoot%) do set result=%destRoot%%sourceFolder:*%%~Na=%
Please note that if destRoot may contain spaces, it must be enclosed in quotes in the FOR command: for %%a in ("%destRoot%") do ...
Got this on another forum, seems to contain the answr I was looking for, sharing here for others:
#echo off
REM YOU NEED THIS
setlocal enabledelayedexpansion
REM If the passed parameter string has any spaces you must quote it
REM we unquote it using ~
set PassedString=%~1
REM May as well do the same with string to split on
set DelimString=%~2
REM The delim string must appear exactly ONCE in the passed string
REM Replace the delim string with a symbol which will not be in the
REM path to be split, in this example I use #
set splitsub=#
call set tempstring=!PassedString:%DelimString%=%splitsub%!
REM Use FOR to split the modified string
for /f "tokens=1* delims=%splitsub%" %%A in ("%tempstring%") do set part1=%%A & set part2=%%B
REM Show that the 2 variables contain the desired substrings
echo Passed = %PassedString%
echo Part1 = %part1%
echo Part2 = %part2%
Example output:
C:\>splitstring.bat "D:\Backup\mystuff\programming\Visual Basic\project\ABCDE\DEF" "project"
Passed = D:\Backup\mystuff\programming\Visual Basic\project\ABCDE\DEF
Part1 = D:\Backup\mystuff\programming\Visual Basic\
Part2 = \ABCDE\DEF
C:\>splitstring.bat "D:\Backup\mystuff\programming\Visual Basic\project\ABCDE\DEF" "mystuff"
Passed = D:\Backup\mystuff\programming\Visual Basic\project\ABCDE\DEF
Part1 = D:\Backup\
Part2 = \programming\Visual Basic\project\ABCDE\DEF

Resources