I've got some *.Xml files in a directory and its sub-directories. I need to loop through the XML files which have a specific constant at the end of their file name, and then echo/print their names without the constant part nor the extension (.Xml).
For example: these are the file names I have:
FileAAA_Constant.Xml
FileBBB.Xml
FileCCC.Xml
FileDDD_Constant.Xml
And this is the output I need:
FileAAA
FileDDD
I've tried this command:
For /R %%X in (*_Constant.Xml) do echo %%~nX
Which outputs this:
FileAAA_Constant
FileDDD_Constant
As you can see, it has removed the extension only, while I need to remove "_Constant.Xml" as well.
This works if the file names contains only one underscore, as indicated in your example:
for /F "delims=_" %%X in ('dir /S /B *_Constant.Xml') do echo %%X
If the desired file names may contain more than one underscore, use Pokechu22's answer.
Fairly easy if the exact length of the phrase is known; you just need to use the %var:~0,-3% syntax. Since "_Constant" is 9 chars long, you would want %var:~0,-9%, which takes text from the start (0) to 9 chars from the end (-9). Aditionally, delayed variable expansion also must be enabled with setlocal ENABLEDELAYEDEXPANSION for this to be run inside of your For loop.
Here's a full example:
#Echo off
setlocal ENABLEDELAYEDEXPANSION
for /R %%X in (*_Constant.Xml) do (
set FileNameTemp=%%~nX
echo !FileNameTemp:~0,-9!
)
Note that if you have a file named just _Constant.xml, this will produce "ECHO is off." rather than "" (no output). This can be solved by changing echo !FileNameTemp:~0,-9! to echo. !FileNameTemp:~0,-9!, but that puts a space before each output.
Here's the loop alone:
for /R %%X in (*_Constant.Xml) do (
set FileNameTemp=%%~nX
echo !FileNameTemp:~0,-9!
)
Related
I want to make a program that takes the content of the second line of a text file and puts it on the first. (It doesn't matter if the second doesn't get edited)
for /f "tokens=1" %%t in (file.txt) do set string1=%%t
for /f "tokens=2" %%t in (file.txt) do set string2=%%t
echo %string1%%string2%>file.txt
I have two issues hat I can't seem to be able to fix.
One: the loops only include the first word of each line in the variables.
Two: Echo doesn't replace the first line of the file with the variables given and instead writes ECHO command deactivated (I have the French version of Windows 10 and simply translated what got written in the file, the text in English Windows version might be slightly different, but you get the idea)
If you have any suggestions, I would appreciate if you explain what the code you provide does (I always like to learn)
Your question is not clear and can be understood in several different ways. Anyway, this management is simpler with no for command:
#echo off
setlocal EnableDelayedExpansion
< file.txt (
rem Takes the content of the first line
set /P "line1="
rem Takes the content of the second line and puts it on the first
set /P "line2="
echo !line1!!line2!
rem It doesn't matter if the second line doesn't get edited
echo !line2!
rem Copy the rest of lines
findstr "^"
) > output.txt
move /Y output.txt file.txt
The FOR command uses a space as a delimiter by default. So you have to tell it to not use any delimiters with the DELIMS option. Also, you should be able to do this with a single FOR /F command. Just hold the previous line in a variable.
#ECHO OFF
setlocal enabledelayedexpansion
set "line1="
(for /f "delims=" %%G in (file.txt) do (
IF NOT DEFINED line1 (
set "line1=%%G"
) else (
echo !line1!%%G
set "line1="
)
)
REM If there are an odd amount of lines, line1 will still be defined.
IF DEFINED line1 echo !line1!
)>File2.txt
EDIT: I think I completely misunderstood your question. Once you clarify your question I will repost a code solution if needed.
Use skip to omit the first line and write the 2nd line twice. In general an edit of a file implies a rewrite to a new file and possibly a rename to retain the old file name.
:: Q:\Test\2018\07\25\SO_51508268.cmd
#Echo off
Set "flag="
( for /f "usebackq skip=1 delims=" %%A in ("file1.txt") Do (
If not defined flag (
Echo=%%A
Set flag=true
)
Echo=%%A
)
) >file2.txt
Del file1.txt
Ren file2.txt file1.txt
After running the batch a file1.txt with initially numbered lines 1..5 looks like this:
> type file1.txt
2
2
3
4
5
I have two .txt files. One contains numbers, and the other one contains filepaths. I want to combine these two files to a .csv. The combination is based on wether the number (from nrs.txt) is in the string of the filepath (nodups.txt).
Now I have the following code for this:
#setlocal enableextensions enabledelayedexpansion
for /F %a IN (Output\nrs.txt) DO (
SET "nrs=%a"
for /F %b IN (Output\nodups.txt) DO (
SET "pathstring=%b"
SET csvdelim=,
IF NOT x!pathstring:%nrs%=""!==x%pathstring% %nrs%,%pathstring%>>new2017.txt
)
)
#endlocal
However, I keep having the following issues with the code:
The pathstring never seems to get set. (when I run the code without the if statement, The nrs variable gets set but the pathstring is set to %b). I've seen a lot of possible solutions on here already but none seem to work for me (setting variables like !var! and using usebackq).
The IF statement in the second for loop gets the following error message =""!==x%pathstring% was unexpected at this time. The ="" should remove the nr. from the path (if its there). When I replace "" with something else it still does not work.
The file contents are:
File nrs.txt:
12345
12245
16532
nodubs.txt:
C:\tmp\PDF_16532_20170405.pdf
C:\tmp\PDF_1234AB_20170405.pdf
C:\tmp\PDF_12345_20170506.pdf
Desired output:
12345, C:\tmp\PDF_12345_20170506.pdf
16532, C:\tmp\PDF_16532_20170405.pdf
I really hope someone can help me out with this !
This solution use a different approach, based on arrays:
#echo off
setlocal EnableDelayedExpansion
rem Load array from nodubs.txt file
pushd "Output"
for /F "tokens=1,2* delims=_" %%a in (nodubs.txt) do set "nodubs[%%b]=%%a_%%b_%%c"
rem Process nrs.txt file and show output
(for /F %%a in (nrs.txt) do (
if defined nodubs[%%a] echo %%a, !nodubs[%%a]!
)) > new2017.txt
In a batch file for variables need two percent signs.
There is no need to put %%A into a variable, use it directly.
#setlocal enableextensions enabledelayedexpansion
for /F %%a IN (Output\nrs.txt) DO (
findstr /i "_%%a_" Output\nodups.txt >NUL 2>&1 || >>new2017.txt Echo %%a
)
#endlocal
Instead of a second for, I'd use findstr to search for the entry of nrs.txt enclosed in underscores.
if no find use condiotonal execution on failure || to write to the new file.
According to changed preliminaries another answer.
#Echo on
Pushd Output
for /F "tokens=1-3 delims=_" %%A IN (
' findstr /G:nrs.txt nodubs.txt'
) DO >>"..\new2017.txt" Echo %%B, %%A_%%B_%%C
Popd
sample output:
> type ..\new2017.txt
16532, C:\tmp\PDF_16532_20170405.pdf
12345, C:\tmp\PDF_12345_20170506.pdf
I have several files in a folder with names like
"prefix (S-N 12RE3123) suffix.pdf"
I would like to rename them to just "12RE3123.pdf", removing the prefix and suffix. The issue is that both the prefix and suffix are of varying lengths/ characters, so I cannot just rename by removing the first/last xx characters, but have to use the only commonality where only the characters inside the parenthesis following "S-N" are those to be kept.
There is one special case where a few of the serial numbers are named as WD-12RE3123, and I need to remove the WD- as well. If I had to do it manually, there aren't a lot of them like that so it wouldn't be the end of the world, but having it automated would be nice. I thought of maybe doing an if statement after the removal of prefix/suffix to check if the first 3 characters match WD- then remove those if true, but I am not sure on the implementation.
I am still a novice in batch or vbscript, so I was wondering if this can be done in either of those. Batch has the method "REN" to rename files, but since the final name depends upon what the current name is I am not sure how to set up delimiters or how to approach this.
Any assistance would be greatly appreciated.
Here is a simple solution for your request. It relies on the following facts:
the prefix portion does not contain any parenthesis ( or ) on its own (suffix might though);
the serial number does not contain any parentheses ( or ) on its own;
there are no duplicate serial numbers, also with respect to removal of potentional WD- strings;
This is the code (after having tested the code on the files in your target folder, you need to remove the upper-case ECHO command to actually rename the files):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Set constants here:
set "LOCATION=.\test"
set "PATTERN=*.pdf"
set STRINGS="S-N " "WD-"
cd /D "%LOCATION%"
for /F "eol=| delims=" %%K in ('dir /B "%PATTERN%"') do (
for /F "eol=| tokens=2 delims=()" %%L in ("%%~nK") do (
set "NAME=%%L"
setlocal EnableDelayedExpansion
for %%J in (%STRINGS%) do (
if "!NAME!"=="%%~J!NAME:*%%~J=!" (
set "NAME=!NAME:*%%~J=!"
)
)
ECHO ren "%%~fK" "!NAME!%%~xK"
endlocal
)
)
endlocal
exit /B
How it works:
the first section specifies the folder location, the file pattern and the strings to remove (after having extracted the portion within ()); adapt the values to your needs;
there are several nested for loops; the outermost one simply iterates all the files matching the given pattern (it basically reads and parses the output of a dir command applied on the given files and loops through the returned items; opposed to a standard for loop, this for /F method ensures that the entire folder is read before the loop starts iterating, which is necessary when modifying the enumerated folder content like we do here by renaming files; see also this thread about that issue);
the next for /F loop extracts the file name portion of interest, that is everything between the first pair of parenthesis, and stores it in variable NAME; this loop iterates once only per file;
the is another for loop which walks though all items in the STRINGS variable;
the if clause checks whether the current item of STRINGS occurs at the very beginning of the NAME value; if so, it is removed, otherwise not; this is just a safety query because perhaps a serial number might also contain a given STRINGS item in the middle or at the end (for instance, 123-WD-45A);
at this point, the renaming is performed (after having removed ECHO, of course);
the toggling of delayed expansion is intended to avoid trouble with some special characters in the file names;
And here is another script that uses a more complex method for extracting the interesting parts of the file names. It relies on the following facts:
there occurs only a single substring (S-NSPACE in the file name
the serial number is followed by a );
the serial number does not contain any parentheses ( or ) on its own;
there are no duplicate serial numbers, also with respect to removal of potentional WD- strings;
The code looks like this:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Set constants here:
set "LOCATION=.\test"
set "PATTERN=*.pdf"
set "FILTER=(S-N [^()][^()]*)"
set "IDENTIFYER=S-N "
set STRINGS="WD-"
cd /D "%LOCATION%"
for /F "eol=| delims=" %%K in ('
dir /B "%PATTERN%" ^| findstr /I /R /C:"%FILTER%"
') do (
set "NAME=%%K"
setlocal EnableDelayedExpansion
set "NAME=!NAME:*(%IDENTIFYER%=!"
for /F "eol=| tokens=1 delims=)" %%L in ("!NAME!") do (
setlocal DisableDelayedExpansion
set "NAME=%%L"
setlocal EnableDelayedExpansion
for %%J in (%STRINGS%) do (
if "!NAME!"=="%%~J!NAME:*%%~J=!" (
set "NAME=!NAME:*%%~J=!"
)
)
ECHO ren "%%~fK" "!NAME!%%~xK"
endlocal
endlocal
)
endlocal
)
endlocal
exit /B
Basically, this script works similar to the above one, with a few deviations:
the first section specifies a file name filter and the serial number identifyer (S-N) in addition;
the dir command in the outermost for loop is piped into a findstr command to filter out files not containing (S-N and ) and a string (not containing (/)) in between already at the beginning;
the part (S-N and everything before is removed, the result is stored in NAME;
the next for /F loop extracts everything up to but not including the first ) from the NAME value, which constitutes the file name portion of interest; this loop iterates once only per file;
the is another for loop which walks though all items in the STRINGS variable, which does not contain the S-N portion here as this has already been removed before; the rest in this loop is the same as in the above script;
at this point, the renaming is performed (after having removed ECHO, of course);
#ECHO Off
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*(*)*.*" '
) DO (
FOR /f "tokens=1,2delims=()" %%c IN ("%%a") DO (
FOR /f "tokens=1-3delims=- " %%m IN ("%%d") DO (
IF "%%o"=="" (ECHO(REN "%sourcedir%\%%a" "%%n%%~xa"
) ELSE (
ECHO(REN "%sourcedir%\%%a" "%%o%%~xa"
)
)
)
)
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
The required REN commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(REN to REN to actually rename the files.
Apply each filename matching the mask "()." to %%a
Tokenise using ( and ) as delimiters so that the parenthesised portion is in %%d
Re-tokenise using - and as delimiters so that the required number is in %%o for S-N patterns and %%n for WD- pattern.
Show the rename line.
Note: this should work provided the prefix portion does not contain parentheses and the parenthesised portion is exactly as described.
Magoo and aschipfl both provided good pure batch solutions.
I find development of custom batch scripts for every complex renaming task to be tedious, which is why I wrote JREN.BAT - a regex find/replace renaming utility. JREN.BAT is pure script (hybrid JScript/batch) that runs natively on any Windows machine from XP onward. Full documentation is available from the command line via jren /?, or use jren /?? for paged help.
With JREN.BAT, the solution is as simple as (untested):
jren "^.*\((?:S-N (?:WD-)?)(.+?)\).*" "$1.jpg" /fm *.jpg
If I got the regex wrong, it can easily be fixed. You should probably add the /T option to run the command in test mode first, and then remove it when everything looks good.
If you put the command in a batch script, then you must use CALL JREN.
Happy Friday Think-Tank!
I need some assistance with a Batch .BAT script. Specifically I need help with some "IF statement syntax"
I have a script that is renaming files. There are two files, one ending in four digits and the other ending in five digits. The files will be renamed with variables I have already pre-set earlier within my script.
So here is a scenario: We have two files in a directory located at
c:\Users\username\Desktop\test-dir
There are two files within test-dir:
file1.12345
file2.1234
A four digit ending is one variable type (VAR1), whereas a file ending in five digits is another variable type (VAR2).
I need an if statement to:
a) read all the files(s) with the chosen directory (without using a wildcard if possible).
b) determine based on the number of digits after the "." which variable to use.
c) once making that determination rename the file with the appropriate variables.
The final re-naming convention is as so: yyyymmddtype.1234/12345
So basically it would use the datestamp variable I already created, the type variable I already created to be injected by the if statement, and append with the original ending digits of the file.
I know this seems like a lot, but I am more so a bash script guy. I have all the elements in place, I just need the if statement and what feels like a for loop of some kind to tie it all together.
Any help would be great!
Thank you!
Sorry, not the option you where asking for. Instead of iterating over the full list checking each file for extension conformance, iterate over a list of patterns that will filter file list, renaming matching files with the asociated "type"
for %%v will iterate over variable list, for %%a will split the content of the variable in pattern and type, for %%f will generate the file list, filter with findstr using the retrieved pattern and rename matching files with the corresponding "type"
Rename command is preceded with a echo to output commands to console. If the output is correct, remove the echo to rename the files.
#echo off
rem Variables defined elsewhere
set "folder=c:\somewhere"
set "timestamp=yyyymmdd"
rem Rename pattern variables in the form pattern;type
set "var1=\.....$;type1"
set "var2=\......$;type2"
set "var1=\.[^.][^.][^.][^.]$;type1"
set "var2=\.[^.][^.][^.][^.][^.]$;type2"
setlocal enableextensions disabledelayedexpansion
for %%v in ("%var1%" "%var2%") do for /f "tokens=1,* delims=;" %%a in ("%%~v") do (
for /f "tokens=*" %%f in ('dir /a-d /b "%folder%" ^| findstr /r /c:"%%~a"') do (
echo ren "%folder%\%%~f" "%timestamp%%%~b%%~xf"
)
)
endlocal
#ECHO OFF &SETLOCAL
set "yyyymmdd=yyyymmdd"
set "VAR1=VAR1"
set "VAR2=VAR2"
for /f "delims=" %%a in ('dir /b /a-d^|findstr /re ".*\....."') do echo(ren "%%~a" "%yyyymmdd%%VAR1%%%~xa"
for /f "delims=" %%a in ('dir /b /a-d^|findstr /re ".*\......"') do echo(ren "%%~a" "%yyyymmdd%%VAR2%%%~xa"
remove echo( to get it working.
If I understand you then this will rename the two files using preset variables for each one:
for %%a in ("%userprofile%\Desktop\test-dir\*") do (
if "%%~xa"==".12345" ren "%%a" "%variableA%-%variableB%%%~xa"
) else (
ren "%%a" "%variableC%-%variableD%%%~xa"
)
)
I have a folder full of images which have a format filename.com_XXX_IMG_000.jpg. The issue comes because the file name has a .com in it, it confuses the the software that I am using to upload it to a webspace.
I need to create a batch file that gets all the images in a folder and renames all of them from filename.com_XXX_IMG_000.jpg => filename_XXX_IMG_000.jpg.
Any help would be greatful, thanks in advance.
Since you want to do it in a batch file:
#echo off
for /f "delims=. tokens=1,2,3" %%f in ('dir /b *.jpg') do (
setlocal enabledelayedexpansion
set part=%%g
if "!part:~0,3!"=="com" (
set oldname=%%f.%%g.%%h
set newname=%%f.!part:~4!.%%h
echo "!oldname!" -^> "!newname!"
ren "!oldname!" "!newname!"
)
endlocal
)
A few notes
for loop variables are single letter, like this: %f
in a batch file, the % must be escaped, so %f becomes %%f
delims=. splits the filenames at the ., in your case into three parts
tokens=1,2,3 returns three variables containing the individual name parts (%f, %g and %h)
enabledelayedexpansion switches on dynamic variable handling
you can do string manipulation with variables: %foo:~0,3% returns the first three characters of %foo%.
with delayed expansion enabled, you can access variables that change their values by using ! instead of %
the > must be escaped or echo won't print it, hence ^>
read some more on String Manipulation in DOS
read HELP FOR and try the following....
#echo off
setlocal enabledelayedexpansion
for %%a in (*.jpg) do (
set fn=%%~na
set fn=!fn:.com=!
echo REN "%%a" "!fn!.jpg"
)
you need to enable delayed expansion because you need to expand a variable inside the for loop.
the loops iterates over all the jpg files in the current directory and for each file it extracts its filename using the ~n syntax, and then it removes all the occurences of .com by replacing them with an empty string. Read HELP SET
after careful testing, remove the echo command