Use multiple wildcards in a path in batch file - batch-file

First of all, there are similar questions on Stack OverFlow like:
Windows - Batch file ignoring multiple wildcards
How to specify multiple wildcards in a folder directory in CMD
However, my use-case is a bit specific (or let's say: I couldn't manage to solve my problem using the lessons learned from the previous forum entries - mind that I am a pure beginner with Batch files).
What I want to do is to grab a file from a certain path, which includes a few subfolders (which change their names) - and copy it to another path which has similar folder structure.
I am currently stuck at the point, that I don't know how to set multiple wildcards in the source path, as it consists of a few things changing. Example:
File in Source:
C:\20170621_Update2017SR1\Polarion_update\_backup-20170627-1602.05\polarion\plugins\com.polarion.alm.tracker_3.17.0\configuration\MyPolarion\page.xml
Target Directory:
C:\Polarion\polarion\plugins\com.polarion.alm.tracker_3.18.2\configuration\My Polarion
Basically only the parts with numbers can change, so I was trying the following:
for /D %%a in ("C:\Polarion\polarion\plugins\com.polarion.alm.tracker*") do set "com.polarion.alm.tracker=%%a"
for /D %%b in ("C:\*_Update*\Polarion_update\_backup-*\polarion\plugins\com.polarion.alm.tracker*") do set "folder=%%b"
echo %com.polarion.alm.tracker%
echo %folder%
set source="%folder%\configuration\MyPolarion\page.xml"
set destination="%com.polarion.alm.tracker%\configuration\My Polarion"
xcopy /s /Y %source% %destination%
I am pretty sure line 2 of my Code contains mistakes - because I don't know if I can set multiple wildcards like this.
The console gives me for line 2:
Echo is on
I don't understand what it means and what should I do.

As I already mentioned in a comment, wildcards can only be used in the very last element of a path (independent on whether this is a file or directory). That is why your command line containing C:\*_Update*\Polarion_update\... fails. However, you can resolve every directory level with wildcards individually, like this:
set "folder="
for /D %%b in ("C:\*_Update*") do (
for /D %%c in ("%%~b\Polarion_update\_backup-*") do (
for /D %%d in ("%%~c\polarion\plugins\com.polarion.alm.tracker*") do (
set "folder=%%~d"
)
)
)
echo "%folder%"
If there are more than one matching directories on any levels, replace set "folder=%%~d" by echo "%%~d" to view them all.

Related

Windows command line renaming files in subfolders?

I didn't find so far a similar question, so I try to explain the problem:
I have large number of files that are in subfolders inside "C:\images"
I have a list of names in two columns, so that 1st column is old filename and 2nd is a new filename. I want to change that list into a batch file.
Names are pretty unique so I want to make batch file - so that will be one command for every file to be renamed.
RENAME "C:\images\768e11ab.jpg" "4ca5d042.jpg"
RENAME "C:\images\5402c708.jpg" "b802820b.jpg"
RENAME "C:\images\1c039e0e.jpg" "80ce9797.jpg"
etc...
It is rather simple, only, files are scattered across subfolders. Is there any way to make a command so it will look for that specific file in all subfolders in "C:\images" and rename it.
Following some similar questions tried this, with no result:
for /r "C:\images\" "%%~G" (768e11ab.jpg) do "4ca5d042.jpg"
Also, tried to use some renaming application for this but they freeze when I try to rename big list of files, so I would avoid them and use batch file. Also, I would like to use this way where there is one line in batch file for every file because it is simpler for me to use it (and change it later). I appreciate your help.
Approach the problem from the other side. Instead of looping over the image files, loop over the text file.
Assuming your textfile to be something like
"768e11ab.jpg" "4ca5d042.jpg"
"5402c708.jpg" "b802820b.jpg"
"1c039e0e.jpg" "80ce9797.jpg"
Then the code could look like:
#echo off
REM read each line; %%A is the first column, %%B is the second one
for /f "tokens=1,2" %%A in (list.txt) do (
REM search the image file %%A
for /R "C:\Images\" %%C in ("%%~A") do (
REM %%C now holds the full path of %%A
ECHO ren "%%~C" "%%B~%%~xC"
)
)
If your list looks different, the tokens and perhaps the delims for the for /f loop have to be adapted.
NOTE: the ren command is just echoed for security reasons. Once you verified it does exactly what you want, remove the ECHO to enable the * ren` command.

Will this be possible with a batch file?

Before I start posting code I am wondering if this is even feasible.
I have a directory of folders I need to move to a new directory.
But I only need to move the folders that contain only 2 files in them.
The rest of the folders have more than 2 files in them, but they need to stay.
So would this be feasible with a batch file?
This was interesting so I took a stab at it:
#echo off
set "dir=C:\Your\Current\Directory"
set "ndir=C:\Your\New\Directory"
setlocal enabledelayedexpansion
for /d %%A in (%dir%\*) do (
pushd "%%A"
for /f %%B in ('dir /a-d-s-h /b ^| find /v /c ""') do (
set cnt=%%B
if "!cnt!" == "2" (if not exist "%ndir%\%%~nA" robocopy "%%A" "%ndir%\%%~nA" /e)
)
)
pause
I kept running into issues so I modified a few things to make it do what I wanted; there're likely more elegant ways to go about it, but this worked ¯\_(ツ)_/¯. First thing is setting variables for your current directory (dir) and your new directory (ndir) to make it a little easier to digest later on; we also need to enable delayed expansion since the value of our counting variable (cnt) will change between loop iterations. The first FOR loop is /d, which will loop through folders - we set each of those folders as parameter %%A and use that to change our directory (using pushd) prior to running our nested commands.
The second FOR loop is /f, which will loop through command results - the commands in this case being dir and find. For dir we are specifying /a to show all files that -d aren't folders, -s system files, or -h hidden files, and we display that output in /b bare format. Using the output from dir, we run find and specify to /v display all non-empty lines and then /c count the number - which becomes parameter %%B.
Finally, we set %%B as our counting variable (cnt) - if !cnt! is equal to 2, we see if the folder already exists in the new directory, and if it does not we robocopy it over. The move command was giving me some trouble because the folder would be locked by the loop, so if you want you could also throw in a DEL command to delete the original folder.
Let me know if that helps! Hopefully your research was going well anyway.
References: Counting Files, FOR Looping, pushd, DIR, FIND, robocopy

Open multiple directories without knowing the names of said directories and delete folders within them using a Windows batch file

Okay, I do not really know how to describe fully what I want and I feel bad for asking something so advanced. I do not know how to do anything other than move folders and delete files and folders using batch.
I am trying to make a batch file to delete certain Steam files and folders which are used to cache data. I could easily make this for myself and call it a day however I would like to share it and have it work for other people also. The problem is one of the cache folders is named with a unique Steam identifier. I will put what I have made so far below.
REM Makes a temporary folder.
mkdir %LocalAppData%\Temp\steam_cache
REM Deleted all none essential files in Steam's configuration folder.
move "%ProgramFiles(x86)%\Steam\config\config.vdf" %LocalAppData%\Temp\steam_cache
move "%ProgramFiles(x86)%\Steam\config\loginusers.vdf" %LocalAppData%\Temp\steam_cache
rmdir "%ProgramFiles(x86)%\Steam\config" /s /q
mkdir "%ProgramFiles(x86)%\Steam\config"
move %LocalAppData%\Temp\steam_cache\config.vdf "%ProgramFiles(x86)%\Steam\config"
move %LocalAppData%\Temp\steam_cache\loginusers.vdf "%ProgramFiles(x86)%\Steam\config"
REM Delete all none essential files in Steam's userdata folder.
I will put what the file structure goes like below.
%ProgramFiles(x86)%\Steam\userdata\256283931
As you can see the number at the end is completely random and I do not know how to open that directory without knowing the number first. There are sometimes multiple of these folders with random names if you login with multiple account and I would like the batch file to go into them one by one and delete certain folder inside of them.
I will put below the folders that I would like to delete that are inside of the random numbered folder below.
%ProgramFiles(x86)%\Steam\userdata\256283931\ugcmsgcache
Sorry if what I am asking it too much if so just ignore this post, thanks.
What you are looking for is the for /D loop, which enumerates directories:
rem // Enumerate all directories under `userdata`:
for /D %%I in ("%ProgramFiles(x86)%\Steam\userdata\*") do (
rem // Check if there is really a sub-directory called `ugcmsgcache`:
if exist "%%~I\ugcmsgcache\" (
rem // Do something with the full path, like echoing, for instance:
echo "%%~I\ugcmsgcache"
)
)
If you want to ensure that the name of the enumerated directory/-ies name consist(s) of decimal figures only, you could use dir and findstr, together with a for /F loop:
rem // Change into parent directory, because `dir /B` returns plain directory names:
cd /D "%ProgramFiles(x86)%\Steam\userdata"
rem // Enumerate all directories under `userdata`, whose names are pure numbers:
for /F "delims=" %%I in ('
dir /B /A:D "*" ^| findstr /I /X "[0123456789]*"
') do (
rem // Do something with the full path, like echoing, for instance:
echo "%%~fI\ugcmsgcache"
)
The cd command could also be replaced by pushd and popd.
The ~f modifier ensures that the full path is derived, related to the current working directory.
Note that the pipe (|) needs to be escaped here, because it is in the set of the for /F loop.

Changing the path location of a file to the desired path

I want to replace the content paths defined into the file i.e logging.properties to the desired location path of the jboss7 location .
Basically i'm using installer where i have to browse my jboss7 folder and locate it to any desired location of the user . But in few files of jboss7 there are some hardcoded path defined like in given logging.properties file.
I need to change that hard coded path to the desired location path.
As of now i'm having repl.bat and file test.bat files in the same folder.
repl.bat helper file could be find in following link:-
http://www.dostips.com/forum/viewtopic.php?f=3&t=3855
I just copied the code and created repl.bat file.
test.bat file :-
#ECHO OFF
SETLOCAL
SET "folder="
FOR /r "C:\" %%a IN (tintin.txt) do IF EXIST "%%a" SET "folder=%%~dpa"&GOTO got1
FOR /r "D:\" %%a IN (tintin.txt) do IF EXIST "%%a" SET "folder=%%~dpa"&GOTO got1
:got1
echo "%folder%"
PAUSE
set "newpath=%folder%"
set "newpath=%newpath:\=\\%"
echo "%newpath%"
PAUSE
type "logging.properties" | repl "(Directory=).*(\\\\standalone\\\\)" "$1%newpath%$2">"logging.properties.tmp"
PAUSE
move "logging.properties.tmp" "logging.properties"
PAUSE
GOTO :EOF
PAUSE
Here in this test.bat file , i'm searching a file tintin.txt file and setting the path into a variable name as 'folder'. tintin.txt file is just inside the folder of jboss7.This is because of the possibilities of more than one jboss7 application server folder into the system.
Till now i have got the path i.e "C:\Users\Anuj\Desktop\jboss7\" and set into the variable 'folder'.
Now there is file named logging.properties into the folder location
C:\Users\Anuj\Desktop\jboss7\standalone\configuration
logging.properties :-
com.latilla.import.uploadDirectory=C:\\progra~2\\Latilla\\C4i\\jboss7\\ standalone\\uploads
com.latilla.import.maxFilesUploadNumber=10
com.latilla.export.templateFile=C:\\progra~2\\Latilla\\C4i\\jboss7\\standalone\\templates\\GDV_HDI_Format.xls
com.latilla.etl.pluginsRootDirectory=C:\\progra~2\\Latilla\\C4i\\jboss7\\standalone\\cloverETL\\plugins
com.latilla.etl.templatesDirectory=C:\\progra~2\\Latilla\\C4i\\jboss7\\standalone\\etl
com.latilla.db.user=postgres
com.latilla.db.pass=password
repl.bat helper file helps to replace the url path with the desired path i.e path set to variable name 'folder'.
I want to replace the C:\progra~2\Latilla\C4i\jboss7\ with the path set to variable name 'folder'.
Note :-
here in logging.properties file path contents is having different format of path i.e C:\
means double slash. \
Might be the script that i have tried test.bat is incorrect.
When i double click the test.bat file i got error.
Although I can't help you with fixing the issue you are getting while using the repl.bat file, I can suggest a different way of solving the initial problem of path replacement.
If the jboss7 string is guaranteed to be present in all the original paths in your configuration file(s), you could try the following approach:
#ECHO OFF
SETLOCAL DisableDelayedExpansion
FOR /F "delims=" %%A IN ('DIR /B /S C:\tintin.txt') DO (CD /D "%%~dpA" & CALL :got1)
FOR /F "delims=" %%A IN ('DIR /B /S D:\tintin.txt') DO (CD /D "%%~dpA" & CALL :got1)
GOTO :EOF
:got1
SET "propfile=%CD%\standalone\configuration\logging.properties"
IF NOT EXIST "%propfile%" GOTO :EOF
SET "tempfile=%TEMP%\logging.properties.tmp"
FIND /I /V "jboss7\\" >"%tempfile%"
>>"%tempfile%" (
FOR /F "tokens=1,* delims=" %%I IN ('FIND /I "jboss7\\"') DO (
SET "pathname=%%J"
SETLOCAL EnableDelayedExpansion
IF NOT "!pathname!" == "!pathname:*jboss7\\=!" (
SET "pathname=%__CD__:\=\\%!pathname:*jboss7\\=!"
)
ECHO %%I=!pathname!
ENDLOCAL
)
)
ECHO Old file "%propfile%":
TYPE "%propfile%"
ECHO =======================================
ECHO New file:
TYPE "%tempfile%"
PAUSE
:: uncomment the next line once you have verified the replacement works correctly
::MOVE "%tempfile%" "%propfile%"
Searching for the tintin.txt file has been changed slightly so as to possibly make the process faster. Instead of iterating over every directory and checking if it contains the file, the loops now read the output of DIR, which returns only actually existing entries.
Note that you could also use a FOR /R loop, as in your present code, with the same effect i.e. returning only existing paths, but the IN clause would need to contain a mask rather than a normal name, but that would have to be a mask that couldn't match anything else in your system than just tintin.txt. For instance, if you knew for certain that there could be no file called tintin.txt1 or tintin.txtx or anything else where tintin.txt is followed by exactly one character, you could use the following template instead:
FOR /R "C:\" %%A IN (tintin.txt?) DO (CD /D "%%~dpA" & CALL :got1)
and same for D:\. That would return only references to files actually existing and matching the mask.
Also, you can see that the loops do not jump (GOTO) to the got1 label but instead call the got1 subroutine. With that change, it is possible to process many application instances in one go. I don't know yours can be installed multiple times. If not, you'll probably want to change it back to GOTO.
The subroutine in my script is referencing the config file using its full path as specified in your description (...\standalone\configuration\logging.properties). For some reason, in your script the file is referenced simply by its name, even though there's no preceding CD or PUSHD command changing the current directory to the location of the file. I assumed you were trying to simplify your script and omitted that bit, whether intentionally or not. Otherwise I may have missed something in your explanation and/or script.
After verifying that the config file exists at the expected location, the replacement itself is done in this way:
All the non-path config lines are written to a temporary file with one go.
Every config line containing a path is processed in this way:
if it does not contain the jboss7\\ string, it is omitted;
otherwise the part of the path up to and including jboss7\\ is removed;
the current directory is inserted before the remaining part (after every \ is replaced with \\);
the new value is put back into the config line;
the update line is added to the same temporary file.
The old version is of the configuration file replaced with the new one.
Obviously, the script may change the order of lines in the processed file, but it is assumed that that doesn't matter.

Deleting folders and subdirectories when a file extension is found in it

I'm new to the board so please go easy! :)
Basically, I'm writing a batch file to delete folders that don't have a file with a certain extension type in them.
so for example if i have the following folder
C:\MUSIC\FLAC\JAZZ\Jazzysong.ape
I need a bit of code that can delete the folder JAZZ because .ape is the wrong file type for the FLAC folder.
Any help would be awesome guys as I've tried variants of findstr, exist and writing to text file and trying to read the path using dir /s /b
I'm lost
I'm still unsure as to which kind of test you want to perform on a directory before deciding to remove it – "whether a certain file type exists" or "whether a certain file type doesn't exist". Your post seems to suggests it is the latter, so it must be the title that is misleading. For the purpose of this answer, I'm assuming that it is indeed the "whether a certain file type doesn't exist" test that you want.
Here's a very simplistic and unassuming approach to the problem:
#ECHO OFF
FOR /D /R "D:\directory_with_flac_files_only" %%D IN (*) DO (
IF NOT EXIST "%%D\*.flac" ECHO RD /S /Q "%%D"
)
That is, just traverse the directory tree and, for every subdirectory, check if it doesn't contain the necessary files. If it doesn't, say goodbye to it. (For safety, I added ECHO before the RD command, so that it does indeed say its goodbye but does not perform the real action, just in case you rush into executing the script without reading further.)
That approach is wrong, however. Even though a directory may not contain the required files, its sub-directories might, and this script does not verify that fact. As a consequence, you might lose some of your invaluable FLAC files. (And I've just saved you the grief.)
So, something more elaborate is needed here. The method I came up with consists in the following steps:
Sort the directories into two categories: those that contain the files with the necessary extension and those that don't.
Process the list of directories that do not contain the files:
1) if a directory is found in the other list, omit it;
2) if it is not found in the other list, remove it.
(In case you are wondering: a directory from the first list may indeed be found in the second list as part of its subdirectory's path.)
I'm far from being convinced that it's the best approach possible, but at least it should work (it did work for me, anyway). Here's my implementation of it:
#ECHO OFF
:: set the params
SET "ext=flac"
SET "rootdir=D:\dir_with_flac_files_only"
SET "todelete=%TEMP%\dirs_to_delete.txt"
SET "topreserve=%TEMP%\dirs_to_preserve.txt"
:: clear the temp lists
TYPE NUL >"%todelete%"
TYPE NUL >"%topreserve%"
:: sort the dirs
FOR /D /R "%rootdir%" %%D IN (*) DO (
IF EXIST "%%D\*.%ext%" (
ECHO %%D>>"%topreserve%"
) ELSE (
ECHO %%D>>"%todelete%"
)
)
:: process the sorted lists
FOR /F "usebackq delims=" %%D IN ("%todelete%") DO (
FIND "%%D" <"%topreserve%" >NUL || ECHO RD /S /Q "%%D" 2>NUL
)
You can still see the ECHO before RD, but consider it just my way of saying, ‘In case I missed something…’. Run the script and look at the output. If it correctly shows only the directories that are due to be deleted, remove ECHO and run the script again to get on with the action.

Resources