remove the directory from output in batchfile - windows

I have the below batchfile that output ReadFile.txt file
cd /d "T:\EMP\SST"
for /r %%i in (T:\EMP\SST) do echo %%i >>D:\MultiThreading\ReadFile.txt
pause
this ReadFile.txt file output
T:\EMP\SST\T:\EMP\SST
T:\EMP\SST\file 11\T:\EMP\SST
T:\EMP\SST\file 12\T:\EMP\SST
T:\EMP\SST\file 13\T:\EMP\SST
I want to remove the directory ouptput T:\EMP\SST so I want my output to be like this
file 11
file 12
file 13
how to do this

I believe you actually need for /D rather than for /R for your task (because I assume file 11, file 12, file 13 are actually directories as they are enumerated by for /R):
for /D %%I in (T:\EMP\SST\*) do echo %%~nxI
Anyway, your for /R syntax is wrong; the directory you want to enumerate recursively needs to be stated immediately after the /R switch (if you omit it, the current directory is assumed), and you need to provide a set (that is the part in between parentheses) that constitutes a pure file name pattern only, without any (absolute or relative) paths, like *.*, for example, to match all files.
In your code, for /R enumerates the current directory. Since your set is T:\EMP\SST and contains no wildcards (*, ?), it is just appended to the enumerated directories literally, because for accesses the file system only in case wildcards are encountered. That explains your weird output.

you're using FOR in a wrong way. The pattern between the parentheses isn't the start directory, it is the file/directory pattern you want to match. Here I suppose you want *.*
If you only want the filenames (no paths at all) you can write:
#echo off
for /r T:\EMP\SST %%i in (*.*) do echo %%~nxi>>D:\MultiThreading\ReadFile.txt
If you want the filenames + relative paths, it's slightly more complicated but doable, by enabling delayed expansion to be able to remove the path prefix + backslash:
#echo off
setlocal enabledelayedexpansion
set start_path=T:\EMP\SST
for /r %start_path% %%i in (*.*) do (
set f=%%i
echo !f:%start_path%\=!>>D:\MultiThreading\ReadFile.txt
)
This FOR command is cryptic and I have to read the help (FOR /?) everytime, but the fact is: everything useful is in there so I do it all the time :)

Related

Batch File Variable to copy specific files

I'm trying to copy specific files from C: to "X: for example". The files are named with the same format.
A1234_ZZabc123_DT1_F1.tst
A4567_ZZdef4567_DT2_F2.tst
A8901_ZZghi1289_DT1.tst
A2345_ZZjfkbu12_to_modify.tst
A6789_ZZlmny568_F1_to_modify.tst
A1234_ZZabc478_DT1.txt
I want to copy only the .tst files, and with the same format as the first 3 Axxxx_ZZyyyxxx_DTx_Fx.tst where x=number and y=letter.
After ZZ, it might be 4 letters and 3 numbers, or 5 letters and 4 numbers, like a "namecode".
Example: ZZkusha122 or ZZkus1551.
I need to copy the folders along with the files too.
I'm new to coding and really need some help.
I need to find and copy all those files along 10k+ files together
You claim that the first 3 of your example filenames fit the pattern you describe. I believe that only two do.
#ECHO OFF
SETLOCAL
rem The following setting for the directory is a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
FOR /f "delims=" %%e IN (
'dir /b /a-d "%sourcedir%\A*.tst"^|findstr /X /I /R "A[0-9][0-9][0-9][0-9]_ZZ[a-z][a-z][a-z]_DT[0-9]_F[0-9].tst" '
) DO ECHO COPY "%sourcedir%\%%e" X:
)
GOTO :EOF
Always verify against a test directory before applying to real data.
The required COPY commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO COPY to COPY to actually copy the files. Append >nul to suppress report messages (eg. 1 file copied)
Simply execute a dir command that reports only filenames matching the *.tst mask. Filter this list with findstr which /X exactly matches the regular expression provided. findstr only has a limited implementation of regular expressions. The /I forces a case-insensitive match. If you want case-sensitive, remove the /I and change each [a-z] to [a-zA-Z] (leave as-is if you want lower-case only in these positions.)
See findstr /? from the prompt for more documentation, or search for examples on SO.
---- revision to cater for multiple filemasks and subdirectories ---
#ECHO OFF
SETLOCAL
rem The following setting for the directory is a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
SET "maskfile=%sourcedir%\q74442552.txt"
FOR /f "tokens=1*delims=" %%e IN (
'dir /b/s /a-d "%sourcedir%\*.tst"^|findstr /E /I /R /g:"%maskfile%" '
) DO ECHO COPY "%%e" X:
)
GOTO :EOF
Changes:
Establish a file, name irrelevant, as maskfile
The dir command requires the /s switch to scan subdirectories
The filemask for the dir command loses the initial A
The findstr command replaces the /X switch with /E
The findstr command loses the regex expression. These are transferred to a file and the file is nominated by the /g: switch.
The copy command loses the source-directory as the directory will be included in %%e
The file "q74442552.txt" contains lines that are of the form
A[0-9][0-9][0-9][0-9]_ZZ[a-z][a-z][a-z]_DT[0-9]_F[0-9].tst
A[0-9][0-9][0-9][0-9]_ZZ[a-z][a-z][a-z]_to.*.tst
This time, %%e acquires the full pathname of the files found. Since the filemask ends .tst, the only filenames to pass the dir filter will be those that end .tst.
The /e switch tells findstr to match string that End with the regex strings in the file specified as /g:.
The strings in the file must comply with Microsoft's partial regex implementation, one to a line.
In summary, findstr uses as regex
Any character,literally
[set] any character of a set of characters
[^set] any character not in a set of characters
. any character
.* any number of any character
prefix any of the special characters with\ to use it literally
a set may include a range by using low-high
So - you then need to brew-your own using the examples I've supplied. The second line matches Axxxx_ZZyyy_to{anything}.tst for instance.
--- Minor revision to deal with maintaining destination-tree -----
(see notes to final revision for why this doesn't quite work)
#ECHO OFF
SETLOCAL
rem The following setting for the directory is a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
SET "maskfile=%sourcedir%\q74442552.txt"
SET "destdir=u:\your results"
FOR /f "tokens=1*delims=" %%e IN (
'dir /b/s /a-d "%sourcedir%\*.tst"^|findstr /E /I /R /g:"%maskfile%" '
) DO ECHO "%%~nxe"&XCOPY /Y /D /S "%sourcedir%\%%~nxe" "%destdir%\">nul
)
GOTO :EOF
This version adds the destination root directory as destdir.
The dir ... findstr... works as before to list the filenames to copy.
The prior version used echo copy to report the proposed copy operation, but the destination was always the same directory.
The replacement XCOPY line maintains the directory structure at the destination.
Note : the XCOPY is "live". The files will be copied to the destination if run as-is. Always verify against a test directory before applying to real data.
To "defuse" the XCOPY, add the /L switch and remove the >nul. This will cause XCOPY to report the source name that would be copied instead of copying it. (The >nul suppresses the report)
The /D only copies source files that eitherr do not exist in the destination of have a later datestamp in the source.
The action is to xcopy each filename found (%%~nxe) from the source directory tree to the destination. Therefore, any file xyz.tst found anywhere in the source tree will be xcopyd to the destination tree. The /D means that once xyz.tst is encountered on the source tree, it will be skipped should it be encountered again.
--- Final (I hope) revision ---
#ECHO OFF
SETLOCAL
rem The following setting for the directory is a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=U:\Users\tocil\Desktop\aoi"
SET "maskfile=%sourcedir%\q74442552.txt"
SET "destdir=u:\your results"
FOR /f "tokens=1*delims=" %%e IN (
'dir /b/s /a-d "%sourcedir%\*.tst"^|findstr /E /I /R /g:"%maskfile%" '
) DO (
rem drive and path to 'dirname' - has terminal "\"
SET "dirname=%%~dpe"
rem remove the sourcedir from dirname
FOR %%y IN ("%sourcedir%") DO CALL SET "dirname=%%dirname:%%~y=%%"
rem copy or xcopy the file to the destination.
FOR /f "tokens=2delims==" %%y IN ('set dirname') DO XCOPY /Y "%%e" "%destdir%%%y">nul
)
)
GOTO :EOF
Always verify against a test directory before applying to real data.
Note to self: Only if the filemask provided to XCOPY is ambiguous (ie. contains ? or *) will XCOPY obey the /s switch unless the target file exists in the starting source directory.
hence
xcopy /s sourcedir\myfile destdir
will copy myfile from the entire tree ONLY if sourcedir\myfile exists.
xcopy /s sourcedir\myf?le destdir
will copy myfile from the entire tree regardless. Unfortunately it will also copy myfale and myfule as well.
Hence, the new approach.
First, perform a dir /b /s to get all of the filenames and filter as before. This is being assigned to %%e.
Take the drive and path only of the file and assign to dirname.
The next step is a little complex. First, set the value of %%y to the name of the source directory. Next, use a parser trick to remove that name from dirname. The mechanics are: Parse the %%dirname:%%~y=%% (because the call causes the set to be executed in a sub-shell) whuch does the normal left-to-right evaluation. %% is an escaped-%, so is replaced by %; %%y is an active metavariable so is replaced by (the name of the source directory) and the ~ causes the quotes to be stripped from that name. The resultant command executed is thus SET "dirname=%dirname:nameofsourcedirectory=%"
So now we can construct a copy-class instruction. dirname now contains the relative directory for the destination, which we can extract from the environment by parsing a set listing (Could also be done with delayed expansion) where %%y gets set to the relative directory and has both a leading and trailing backslash, so the destination directory is simply "%destdir%%%y". XCOPY then knows to create that directory if necessary (%%y has a trailing backslash) and we know the source filename is in %%e.
You could also use a copy to do the same thing, but you'd need to create the destination directory first. Another advantage of XCOPY is that you can also specify the /d switch to not copy files that have an earlier date over files that have a later date.

Is it possible to use wildcards within a Batch script to grab all directories under a path, and then use the relevant name for the creation of a file

It's a bit of a convoluted title and I apologise for my poor English, it's not my first language and I'm far from fluent. I hope my current code explains my goal better than my written explanation.
#echo off
Setlocal enableextensions enabledelayedexpansion
set BCAT_PATH="C:\\Users\\USER\\Downloads\\FMOD conversion to packable\\0Tools\\bincat"
CD "9temp\\zzz_FSBS_Extract_test"
for /D %%D in (\*) do
"%BCAT_PATH%\\bincat" "%%D\*.ogg" -o "..\\zzz_BuiltOGG_test%%\~ni.tmp"
PAUSE
#echo off
Setlocal enableextensions enabledelayedexpansion
set "BCAT_PATH=C:\Users\USER\Downloads\FMOD conversion to packable\0Tools\bincat"
CD "9temp\zzz_FSBS_Extract_test"
for /D %%D in (*) do FOR %%i in ("%%D\*.ogg") do ECHO "%BCAT_PATH%\bincat" "%%i" -o "..\zzz_BuiltOGG_test\%%~ni.tmp"
PAUSE
Use set "var1=data" for setting string values - this avoids problems caused by trailing spaces. In comparisons; don't assign a terminal \, space or quotes - build pathnames from the elements - counterintuitively, it is likely to make the process easier.
Your CD statement will change to a directory RELATIVE to your current directory, so if you are currently at C:\somewhere to C:\somewhere\9temp\zzz_FSBS_Extract_test. If 9temp\zzz_FSBS_Extract_test is an absolute location, then you'd need \9temp\zzz_FSBS_Extract_test
for /D %%D in (\*) do would set %%D to each directoryname in the root directory. Since you've changed to ..?..9temp\zzz_FSBS_Extract_test, you need * to scan the current directory. You could also use "..?..9temp\zzz_FSBS_Extract_test\*" without changing directory. *I don't know where 9temp\... is, so I've used ..?.. to represent its location.
Note that the command to be executed must follow directly after the do, on the same physical line. I've added ECHO to show the command that would be executed. After you've verified that the command is correct, remove the echo keyword to actually execute the command.
Note that BCAT_PATH is set to C:\Users\USER\Downloads\FMOD conversion to packable\0Tools\bincat The command generated will thus be "C:\Users\USER\Downloads\FMOD conversion to packable\0Tools\bincat\bincat".
I've no idea where %%i is defined in your program. I've inserted it where I believe it should go. That should set %%i to each .ogg filename in the directory %%D in turn. %%~ni should return the name part of that file.
Your output directory would be ..?..9temp\zzz_BuiltOGG_test since your current directory is ..?..9temp\zzz_FSBS_Extract_test . The \ should be placed between the directoryname and the filename.
There is not need for delayedexpansion although setlocal is a good idea.
This will not do for each directory, but instead find each .ogg file recursively, then run the command on each file. Also note, I've added the .exe extension to bincat
#echo off
setlocal & set "BCAT_PATH=C:\Users\USER\Downloads\FMOD conversion to packable\\0Tools\bincat"
cd /d "9temp\\zzz_FSBS_Extract_test"
for /R %%i in (*.ogg) do "%BCAT_PATH%\bincat.exe" "%%~i" -o "..\zzz_BuiltOGG_test\%%~ni.tmp"

Using FOR /R for recursive search only in a subset of folder hierarchy

I want to create a batch file able to apply some processing on each JPG file in a folder hierarchy. The following script file works very well for that case (here I only echo the name of each file, but this should be replaced by some more complex statements in the real application):
:VERSION 1
#echo off
set "basefolder=C:\Base"
for /r %basefolder% %%f in (*.jpg) do echo %%f
Actually, I don't want to explore all the folder hierarchy under %basefolder%, but only a given list of subfolders. This modified script is able to deal with that case :
:VERSION 2
#echo off
set "basefolder=C:\Base"
set "subfolders=A B C"
for %%s in (%subfolders%) do (
pushd %basefolder%\%%~s"
for /r %%f in (*.jpg) do echo %%f
popd
)
Is there a solution to remove the pushd/popd pair of statements, to get something closer to the initial script. I thought that one of the following scripts would do the job:
:VERSION 3
#echo off
set "basefolder=C:\Base"
set "subfolders=A B C"
for %%s in (%subfolders%) do (
for /r %basefolder%\%%~s" %%f in (*.jpg) do echo %%f
)
or, using delayed expansion:
:VERSION 4
#echo off
setlocal enabledelayedexpansion
set "basefolder=C:\Base"
set "subfolders=A B C"
for %%s in (%subfolders%) do (
set "folder=%basefolder%\%%~s"
echo !folder!
for /r !folder! %%f in (*.jpg) do echo %%f
)
but none of them is working. When running the second one, the echo !folder! command in the external loop shows C:\Base\A, C:\Base\B and C:\Base\C as expected, but the inner loop doesn't echo any JPG file, so I guess that the recursive for /r command does not run correctly.
What am I doing wrong ?
Final edit after answers :
Thanks to #aschipfl who provided a link to the answer posted by #jeb on another question, quoted below:
The options of FOR, IF and REM are only parsed up to the special character phase. Or better the commands are detected in the special character phase and a different parser is activated then. Therefore it's neither possible to use delayed expansion nor FOR meta-variables in these options.
In other words, my versions 3 and 4 do not work because when defining the root folder of the FOR /R command, neither the %%~s nor the !folder! are correctly expanded by the expression parser. There is no way to change that, as this is a parser limitation. As I said in a comment below: the root folder option in the FOR /R command is basically only syntactic sugar to avoid the use of pushd/popd before and after the command. As this syntactic sugar is incomplete, we have to stick to the original syntax for some specific use cases, as the one presented here. The alternatives proposed by #Gerhard (using a subroutine CALL) or by #Mofi (parsing the result of a DIR command) are working, but they are neither more readable nor more efficient than the simple pushd/popd version I proposed initially.
My Approach for this would be really straight forward:
#echo off
set "basedir=C:\Base"
set "subfolders="A","B","C""
for %%i in (%subfolders%) do for /R "%basedir%" %%a in ("%%~i\*.jpg") do echo %%~fa
The double quotes inside of the subfolders variable is important here, it will ensure that folder names with whitespace are not seen as separators for the folder names. For instance:
set "subfolders="Folder A","Folder B","Folder C""
Edit
#echo off
set "basedir=C:\Base"
set "subfolders="A","B","C""
for %%i in (%subfolders%) do call :work "%%~i"
goto :eof
:work
for /R "%basedir%\%~1" %%a in (*.jpg) do echo %%~fa
It is in general not advisable to assign the value of a loop variable to an environment variable and next use the environment variable unmodified without or with concatenation with other strings being coded in batch file or defined already above the FOR loop within body of a FOR loop. That causes just problems as it requires the usage of delayed expansion which results in files and folders with one or more ! are not correct processed anymore inside body of the FOR loop caused by double parsing of the command line before execution, or command call is used on some command lines, or a subroutine is used called with call which makes the processing of the batch file much slower.
I recommend to use this batch file for the task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "basefolder=C:\Base"
set "subfolders=A B C "Subfolder D" SubfolderE"
for %%I in (%subfolders%) do for /F "delims=" %%J in ('dir "%basefolder%\%%~I\*.jpg" /A-D /B /S 2^>nul') do echo %%J
endlocal
The inner FOR loop starts for each subfolder defined in subfolders in background one more command process with %ComSpec% /c and the DIR command line appended as additional arguments. So executed is with Windows installed to C:\Windows for example for the first subfolder:
C:\Windows\System32\cmd.exe /c dir "C:\Base\A\*.jpg" /A-D /B /S 2>nul
The command DIR searches
in specified directory C:\Base\A and all it subdirectories because of option /S
for files because of option /A-D (attribute not directory) including those with hidden attribute set
matching the pattern *.jpg in long or short file name
and outputs to handle STDOUT of background command process just the matching file names because of option /B (bare format)
with full path because of option /S.
The error message output by DIR on nothing found matching these criteria is redirecting from handle STDERR to device NUL to suppress it.
Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.
The output to handle STDOUT of background command process is captured by FOR respectively the command process which is processing the batch file. FOR processes the captured output line by line after started cmd.exe terminated itself. This is very often very important. The list of files to process is already in memory of command process before processing the first file name. This is not the case on using for /R as this results in accessing file system, getting first file name of a non-hidden file matching the wildcard pattern, run all commands in body of FOR and accessing the file system once again to get next file name. The for /R approach is problematic if the commands in body of FOR change a file to process like deleting, moving, modifying, copying it in same folder, or renaming a found file because of the entries in file system changes while for /R is iterating over these entries. That can easily result in some files are skipped or some files are processed more than once and it could result also an endless running loop, especially on FAT file system like FAT32 or exFAT. It is never good to iterate over a list of files on which the list changes on each iteration.
Command FOR on usage of /F ignores empty lines which do not occur here. A non-empty line is split up into substrings using a normal space and a horizontal tab as string delimiters by default. This line splitting behavior is not wanted here as there could be full qualified file names containing anywhere inside full name one or more spaces. For that reason delims= is used to define an empty list of delimiters which disables the line splitting behavior.
FOR with option /F would also ignore lines on which first substring starts with ; which is the default end of line character. This is no problem here because of command DIR was used with option /S and so each file name is output with full path which makes it impossible that any file name starts with ;. So the default eol=; can be kept.
FOR with option /F assigns by default just first substring to specified loop variable as tokens=1 is the default. This default can be kept here as splitting the lines (full file names) into substrings is disabled already with delims= and so there is always the full file name assigned to the loop variable.
This example uses just echo %%I to output the file names with full path. But it is now safe to replace this single command by a command block which does more with the JPEG files because of the list of JPEG files for each specified subfolder tree in base folder is always already completely in memory of command process processing the batch file.

How do I get a relative path out of a windows batch file using echo?

How do I get relative directories / partial paths to display as echo output from a windows .bat file?
How to split the filename from a full path in batch?
Talks about everything but.
I've found drive letters, filenames, extensions, shortened (8.3) names, and full paths - but no relative paths.
I'm running a recursive FOR /R loop; which traverses sub-directories. I would like something - that doesn't have twenty characters of useless path info - that tells me which directory each duplicate file lives in... without hardcoding the .bat file to live in a certain directory/path?
Maybe a solution would be to measure the length of the script's path and cut that off of the front of the full path? But I don't know how to manipulate that.
Script could be in many locations:
F:\a.bat<BR>
F:\Dir1\fileA.txt<BR>
F:\Dir20\fileA.txt
C:\Users\Longusername\Desktop\Container\a.bat<BR>
C:\Users\Longusername\Desktop\Container\Dir1\fileA<BR>
C:\Users\Longusername\Desktop\Container\Dir20\fileA
And right now the only options I have for output are (%%~nxG):
fileA.txt
fileA.txt
Which doesn't tell me which directory each file is in...or (%%~pnxG)
\Users\Longusername\Desktop\Container\Dir1\fileA.txt
\Users\Longusername\Desktop\Container\Dir20\fileA.txt
What I'd like, from any location:
\Dir1\fileA.txt
\Dir20\fileA.txt
Could be missing the leading \, but that's negligible. Other options than echo are permissible if they'll work on most window machines. They may lead to more questions, though - as I've figured out my other pieces with echo.
quite easy, if you think about it: just remove the current directory path (%cd%):
#echo off
setlocal enabledelayedexpansion
for /r %%a in (*.txt) do (
set "x=%%a"
echo with \: !x:%cd%\=\!
echo without \: !x:%cd%\=!
)
By the way: \folder\file always refers to the root of the drive (x:\folder\file), so it's not exactly a relative path.
This is similar to the already accepted answer, but with delayed expansion enabled only where needed. This should correctly output filenames containing ! characters.
#Echo Off
SetLocal DisableDelayedExpansion
Set "TopLevel=C:\Users\LongUserName"
For /R "%TopLevel%" %%A In ("*.txt") Do (
Set "_=%%A"
SetLocal EnableDelayedExpansion
Echo=!_:*%TopLevel%=!
EndLocal
)
Pause
You could also use Set "TopLevel=%~dp0", (the running script's directory) or Set "TopLevel=%~dp0..", (the running script's parent directory)
One potential benefit of the above method is that you can also use a location relative to the current directory for the value of %TopLevel% too, (in this case, based upon the initial example, the current directory would be C:\Users):
Set "TopLevel=LongUserName"
Although this would only work correctly if LongUserName didn't already exist as content of the path earlier in the tree.
You could use xcopy together with its /S (include sub-directories) and /L (list but do not copy) options since it returns relative paths then, so you do not have to do any string manipulation, which might sometimes be a bit dangerous, particularly when the current directory is the root of a drive:
xcopy /L /S /I /Y /R ".\*.txt" "\" | find ".\"
The appended find command constitutes a filter that removes the summary line # File(s) from the output.
To capture the output of the aforementioned command line just use a for /F loop:
for /F "delims=" %%I in ('
xcopy /L /S /I /Y /R ".\*.txt" "\" ^| find ".\"
') do (
rem // Do something with each item:
echo/%%I
)

For loop in batch file reading a file of File Paths

I want to write a Windows batch file script that will loop through a text file of FILE PATHS, do some work using data from each file path, then ultimately delete the file.
I started by running the FORFILES command and sending its output (the #PATH parameter is the full path of any file it matches) to a text file (results.txt).
I end up with a results.txt file like this:
"C:/Windows/Dir1/fileA.log"
"C:/Windows/Dir1/fileA.log"
"C:/Windows/Dir2/fileC.log"
"C:/Windows/Dir3/fileB.log"
What I want to do is:
Use a FOR loop and read each line in the results.txt file
For each line (file path), strip out the directory name that the log file is sitting in (ie: Dir1, Dir2, etc..) and create a directory with that SAME name in a different location (ie. D:/Archive/Backups/Dir1, D:/Archive/Backups/Dir2, etc..) -- assuming the directory doesn't exist.
Move the actual .log file to a zip file in that directory [I have code to do this].
Delete the .log file from its original location. [Pretty straightforward]
I'm having trouble figuring out the best way to accomplish the first 2 steps. My FOR loop seems to stop after reading the very first line:
FOR /F "tokens=1,2,3,4,5,6,7,8,9,10 delims=\" %%G in ("results.txt") DO (
...
)
You don't want to parse the path with the tokens/delims options because you don't know how many directory levels you are dealing with. You want to preserve each line in its entirety. TO parse the path you want to use the FOR variable modifiers. (type HELP FOR from the command line and look at the last section of the output)
%%~pG gives the path (without the drive or file name). If we then strip off the last \, we can go through another FOR iteration and get the name (and possible extension) of the file's directory by using %%~nxA.
The toggling of delayed expansion is just to protect against a possible ! in the path. If you know that no path contains ! then you can simply enable delayed expansion at the top of the script and be done with it.
EDIT - this code has been modified significantly since Aacini pointed out that I misread the requirements. It should satisfy the requirements now.
for /f "usebackq delims=" %%G in ("results.txt") do (
set "myPath=%~pG"
setlocal enableDelayedExpansion
for /f "eol=: delims=" %%A in ("!myPath:~0,-1!") do (
endlocal
if not exist d:\Archive\Backups\%%~nxA md d:\Archive\Backups\%%~nxA
rem ::zip %%G into zip file in the D: location
rem ::you should be able to create the zip with the move option
rem ::so you don't have to del the file
)
)
I wrote this to timestamp files before offloading to SFTP.
Hope you find it useful.
The timestamp coding may seem irrelevant to your issue, but I left it because it's a good example of dissecting the filename itself.
I suggest you put an ECHO in front of the REN command for testing. Different shells may have different results.
In the end, the delayedexpansion command wasn't necessary. It was the sub-routine that fixed my issues with variables inside the loop. That could possibly be because of my OS ver. (Win 8.1) - It wouldn't hurt to leave it.
#echo off
cls
setlocal enabledelayedexpansion
if %time:~0,2% geq 10 set TIMESTAMP=%date:~10,4%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%
if %time:~0,2% leq 9 set TIMESTAMP=%date:~10,4%%date:~4,2%%date:~7,2%_0%time:~1,1%%time:~3,2%%time:~6,2%
echo TimeStamp=%TIMESTAMP%
echo.
for %%G in (*.txt) do (
set OLDNAME=%%G
call :MXYZPTLK
)
dir *.txt
goto :EOF
:MXYZPTLK
echo OldName=%OLDNAME%
ren %OLDNAME% %OLDNAME:~0,-4%_%TIMESTAMP%%OLDNAME:~-4,4%
echo.
:END
You have two minor problems:
The path separator in the file is '/' but you use '\' in the for loop.
The quotes around "results.txt" stop it working.
This works. Don't write quotes to results.txt and you won't get a quote at the end of the filename.
#echo off
FOR /F "tokens=3,4 delims=/" %%I in (results.txt) DO (
REM Directory
echo %%I
REM File
echo %%J
)

Resources