Removing date and time stamp from a string with spaces in batch - batch-file

I am making a program that automatically backs up files, stores up to a maximum of five of them, and has an option to restore any of the five files. When the files are backed up, it adds a date and time stamp in the format of YYYYMMDD_HHMMSS_filename.ext. In order to restore the file, it is necessary to first cut out the date stamp.
The method I am currently using to cut the date stamp off of the beginning of the file is as follows.
set VAR=%VAR:~16%
echo %VAR%
The problem being, if the backed up file is called "20120825_140343_file name.txt", the above method will only return "file," omitting anything after the space. The spaces in the file names need to be preserved for them to be recognized by the program using them.
tl;dr I need to cut the string 20120825_140343_file name.txt into just "file name.txt", but my method just returns "file."
If delimiters or something would help I could separate the date stamp and file name with a different character, I.E. 20120825_140343-file-name.txt

Your method, though inelegant and inflexible, should work. This tells me that you are not storing the entire filename in VAR. That is why %var:~16% only results in file, and not file name.txt. I assume that you assign VAR like this somewhere:
SET VAR=%1
You'll need to either do this:
SET VAR=%1 %2
Or insert double-quotes around the file name when you call your batch file, and then set var like this to remove the quotes:
SET VAR=%~1
That should be enough to get your batch to work.
====================================================
But, to answer the question you actually asked, I'll show you a method of extracting "file name.txt" from var that will work even if there are more or even less than 16 prefix characters.
Use the for /f statement, specify the 3rd token, with underscores as a delimiter. Here is a self-contained example. (To run from the command-line, change %%x to %x.
SET VAR=20120825_140343_file name.txt
for /f "tokens=3 delims=_" %%x in ("%VAR%") do set VAR=%%x
ECHO %VAR%
Just remember, this solution will NOT fix your problem if you do not fix your code to assure your VAR variable has the entire filename in it.

Have you tried this?
set VAR="%VAR:~16%"

Related

Escape characters of a file path argument for a batch file

I was making a batch file to take dragged-and-dropped folders for program input. Everything was working fine until I passed a folder, which for the sake of this post, called foo&bar.
Checking what %1 contained inside the batch file looked like C:\path\to\foo or C:\path\to\foo\foo. If the file path were in quotes it would work, so the only working code that slightly takes this into effect is :
set arg1=%1
cd %arg1%*
set arg1="%CD%"
Which changes directory to the passed argument using wildcards. However this only works once for if there is another folder with un-escaped characters inside the parent folder, passing the child folder would result in the parent folders' value.
I tried the answer of this post, which suggests to output the argument using a remark and redirection statement during an #echo on sequence. However no progress occurred in rectifying the problem. Any suggestions?
To recap, I am looking for ways to pass folders with un-escaped characters as arguments to a batch file. The implementation should preferably be in a batch file, but answers using VBScript are welcome. However the starting program must be in batch as this is the only program of the 3 that accepts files as arguments.
To test this, create a batch file with following code:
#echo off
set "arg1=%~1"
echo "the passed path was %arg1%"
pause
Then create folders called foobar and foo&bar. Drag them onto the batch file to see their output. foo&bar will only return C:\path\to\foo.
OK, so the problem is that Explorer is passing this as the command line to cmd.exe:
C:\Windows\system32\cmd.exe /c ""C:\path\test.bat" C:\path\foo&bar"
The outermost quotes get stripped, and the command becomes
"C:\working\so46635563\test.bat" C:\path\foo&bar
which cmd.exe interprets similarly to
("C:\working\so46635563\test.bat" C:\path\foo) & bar
i.e., bar is considered to be a separate command, to be run after the batch file.
The best solution would be to drag-and-drop not directly onto the batch file but onto, say, a vbscript or a Powershell script or a plain old executable. That script could then run the batch file, either quoting the argument appropriately or putting the directory path into an environment variable rather than on the command line.
Alternatively, you can retrieve the original command string from %CMDCMDLINE% like this:
setlocal EnableDelayedExpansion
set "dirname=!CMDCMDLINE!"
set "dirname=%dirname:&=?%"
set "dirname=%dirname:" =*%"
set "dirname=%dirname:"=*%"
set "dirname=%dirname: =/%"
for /F "tokens=3 delims=*" %%i in ("%dirname%") do set dirname=%%i
set "dirname=%dirname:/= %"
set "dirname=%dirname:?=&%"
set dirname
pause
exit
Note the exit at the end; that is necessary so that cmd.exe doesn't try to run bar when it reaches the end of the script. Otherwise, if the part of the directory name after the & happens to be a valid command, it could cause trouble.
NB: I'm not sure how robust this script is.
I've tested it with the most obvious combinations, but YMMV. [It might be more sensible to use delayed expansion exclusively, I'm not sure. It doesn't seem to be necessary except in the first set command. Jeb's answer here might be a better choice if you're going this route.]
For the curious, the script works like this:
Load the original command line into dirname [necessary for the reason pointed out by jeb]
Replace all the & characters with ?
Replace all the quote marks with *
If a quote mark is followed by a space, suppress the space.
NB: it is necessary to suppress the space to deal with both the case where the path contains a space (in which case Explorer adds quote marks around it) and the case where it doesn't.
Replace all remaining spaces with /
NB: ? * and / are illegal in file names, so these replacements are safe.
At this point the string looks like this:
C:\Windows\system32\cmd.exe//c/**C:\path\test.bat**C:\path\foo?bar**
So we just need to pull out the third asterisk-delimited element, turn any forward slashes back into spaces and any question marks back into ampersands, and we're done. Phew!

Batch file how to delete end text in a variable string in a for loop

I am writing some batch code to simplify a process I have of downloading some files, renaming them, and then copying them to replace the old ones. I'm running into an issue where I have a FOR loop read in a list of files from a directory, then try to modify the filenames.
The filenames all have FLY in the name, and I want to remove all text after FLY. I can't use tokens because the filenames are inconsistent in length, have multiple spaces, and wouldn't have a set number of tokens. I can't use substring because there is not a set number of characters after FLY.
I've tried using the examples at SS64 and also read numerous threads on here but nothing really seems to match my situation.
Here's the code snippet, appreciate if someone can tell me where I'm going wrong:
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "TOKENS=*" %%A IN ('DIR /B ^"%~DP0VFR^"') DO (
SET FILENAME=%%A
SET REMOVETEXT=!FILENAME:*FLY=!
SET NEWFILENAME=!FILENAME:!REMOVETEXT!=!
ECHO !FILENAME! will be renamed !NEWFILENAME!
)
When I insert echos to see what's going on everything works as expected up until the last SET, where somehow the ending result is !NEWFILENAME! is blank.
Hmm. My results were different from yours.
The " in your dir do not need to be escaped.
The problem with your set statement is that it's interpreted as
SET NEWFILENAME=!FILENAME:! + REMOVETEXT + !=!
and since FILENAME: and = are not existing variables, each will be replaced by nothing yielding "REMOVETEXT", not blank as you claim.
The solution is to use a two-stage evaluation of newname
call SET NEWFILENAME=%%FILENAME:!REMOVETEXT!=%%
which is resolved as
SET NEWFILENAME=%FILENAME:current_value_of_REMOVETEXT=%
in a sub-shell.
After cold brew it occurred to me that I might be going about this all wrong and making it more complicated than it needs to be... I decided to try directly renaming the files with wildcards and that actually worked. Didn't even need the FOR loop.
REN "%~DP0VFR\*FLY*" *FLY
No idea why the first (and overly convoluted) solution I tried didn't work, but this does with a lot less code!

Windows batch file ren using date variable

Learned batch a while ago in school, haven't ever used it until now b/c I had an idea. Just for fun I wanted to mess around with powercfg batteryreport with my new laptop, but I want to archive. I was going to try and figure out how to have the file powercfg batteryreport spits out changed in some sort of numerical order but I don't even know where to begin, so I decided to just make a new line that takes the current file created and adds the date. All of this is taking place inside of a special folder I created, so pathing isnt necessary.
#echo off
powercfg batteryreport
rename "battery-report.html" "batteryreport %date%.html"
This exact script works without the date variable, but never with it in, but of course I need a variable present in order to have multiple reports saved, as opposed to it writing over itself every time. I've tried messing with all spacings, quotes vs no quotes, no luck. Help (or a better way, preferably with explanation) would be greatly appreciated.
In all likelihood, your date format contains / which is illegal in a filename.
Use %date:/=-% in place of %date%. this converts each / to - (see set /? from the prompt for docco)
Equally, you could use %time::=.% o convert the time to a version usable in a filename.
To remove dayname, you need to use an intermediate variable:
set "dateonly=%date:* =%"
ren ... "...%dateonly:/=-%..."
The * means "all of the characters up to and including the first space" and this is replaced by nothing (the string following the =)
see set /? from the prompt for details.

Pick a specific folder in a Path and the name of a file to set 2 differents variables

Sorry to ask a question which will be an easy one for many of you I guess...
I'm a student in a CG School, but for the need of my project I need to code a simple .bat file to run on many computers. Everything works pretty fine, but now I need to simplify it to gain extra time setting up the .bat.
We have ALWAYS a Path like that :
D:\Project\Production\Shot\Render\Room\maya\scenes\Room_01.mb
I need two variables which store :
project : D:\Project\Production\Shot\Render\Room\maya
scene : Room_01
I think I need a loop which analyzes the path backward and sets the path after seeing 2 \ in order to avoid the file name, and the scenes folder. And I need an other thing to store all the file name ######.mb removing the .mb
I tried many things with substring forum, but it's kinda black magic for me...
So if anyone could help, I would be so grateful to you ! :)
Thank you in advance.
An easy solution is to use a for command. It will allow you to retrieve different properties of a file system reference.
set "fileReference=D:\Project\Production\Shot\Render\Room\maya\scenes\Room_01.mb"
for %%a in ("%fileReference%") do set "scene=%%~na"
Where %%~na is the name of the element being referenced by the for replaceable parameter %%a
for %%a in ("%fileReference%\..\..") do set "project=%%~fa"
Where %%~fa is the full path of the element being referenced by the for replaceable parameter %%a
A for loop is typically needed here. The first for loop grabs the last element of the string when split by a backslash. The path is then modified to have the file name removed from it, and then another for loop grabs the end off that string in the same manner.
#echo off
set my_path=D:\Project\Production\Shot\Render\Room\maya\scenes\Room_01.mb
for %%F in ("%my_path%") do set file=%%~nxF
echo.%file%
call set modded_path=%%my_path:\%file%=%%
for %%F in ("%modded_path%") do set folder=%%~nxF
echo.%folder%

Batch program script problem breaks with file names with spaces

The following is a batch script that calls mp3splt (a program that splits mp3s http://mp3splt.sourceforge.net/mp3splt_page/home.php) into partitions of 5 mins long.
for /f %%a IN ('dir /b *.mp3') do call c:\PROGRA~1\mp3splt\mp3splt -t 5.0 -o output\#f+-+#n+-+#t %%a
It breaks when the mp3 files contain a space. Can anyone propose a workaround?
for %%a IN (*.mp3) do (
call c:\PROGRA~1\mp3splt\mp3splt -t 5.0 -o output\#f+-+#n+-+#t "%%a"
)
What others are saying here to quote the variable is doubtless correct. That's needed for it to work correctly. But it also is only half the solution.
Your problem here is that dir /b spits out lines of text, each one containing a single file name, like so:
foo bar.mp3
baz gak.mp3
track01.mp3
...
for /f on the other hand is made for reading files or something else (the dir output in this case) line by line ... but it also does tokenizing. That means it splits strings at configurable places into individual tokens.
By default, /F passes the first blank
separated token from each line of each
file. Blank lines are skipped. You
can override the default parsing
behavior by specifying the optional
"options" parameter. This is a quoted
string which contains one or more
keywords to specify different parsing
options. —help for
So you only get the part before the first space of the file name. You can work around that by using
for /f "delims=" in ...
to specify that tokenizing should be done with no delimiters, essentially giving you the complete line each time. But a better way is actually the one I outlined at the start to just use the regular for to iterate over the files. No surprises with spaces in file names there and it actually makes your intent a lot clearer.
I am regularly surprised why people tend to choose a convoluted and wrong solution over a simple, clear and correct one.
You can quote the variable containing the file name:
"%%a"

Resources