Writing a batch file program using wildcards - windows

Write a batch program called EX4.BAT which lists all files matching any of the following criteria within the root of the C: drive and down through its subdirectories:
a) Files with an extension of .COM and have 4 letters in the filename. e.g. chcp.com, mode.com etc.
b) .EXE files whose 2nd letter is I e.g., WINHELP.EXE DIAGS.EXE etc.
Make sure the output does not scroll up the screen too quickly.
Put a pause command in between parts a) and b)
I tried the following :
cd\ Rem to return to the root folder of C
dir ????.com /b/s Rem COM files with 4 letters
pause Rem to pause the screen
dir ?I*.exe /s Rem search EXE files whose 2nd letter is I
For part a), doing this like that accept also numbers, I have to make sure that it accepts only letters. I tried to make use of regular expression but in vain.

Here is a basic example of one method of performing the task laid out in your question, and without the clarification requested in the comment area.
#Echo Off
Setlocal EnableExtensions
Set "PATHEXT="
( "%__APPDIR__%where.exe" /R C:\ ????.com |^
"%__APPDIR__%findstr.exe" /E /I /R "\\[a-Z]*\.com"
Echo(
Echo Press any key to continue . . .
Pause 1> NUL
"%__APPDIR__%where.exe" /R C:\ ?I*.exe
) 2> NUL | "%__APPDIR__%more.com"
EndLocal
Pause
As this is clearly 'homework' I will not be providing any explanation of the commands I have used, or why I have done so, I will also not be adjusting my code to cater for later additions or changes in the task. It is also important to remember, that as this is technically somebody else's submission, you must not present it unless you fully understand how and why it works.

Related

How can I remove a specific part of many folders names using .bat files?

My university is using a proprietary system that outputs data in a very specific way in which each "module" is output into folders following the structure (4 digit numeral) - (name of module)
ex: 5574-CHEM104
I need to remove the name and hyphen so that only the numeral remains:
5574-CHEM104 > 5574
The problem is that there's thousands of these folders and there's no way I could do it by hand. I'm having difficulty trying to automate the process, so if anyone could at least point out a command I could look into it would help immensely
I've tried the REN command, putting "REN 5574-CHEM104 5574", but it only works for one folder. There's thousands of folders, each with different numerals, under "CHEM104", for example, and I need for the program to rename the folder no matter the original name into the first 4 original numerals, which I can't figure out. Thanks!
#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 /ad "%sourcedir%\*" '
) DO FOR /f "delims=-" %%o IN ("%%e") DO ECHO REN "%sourcedir%\%%e" "%%o"
)
GOTO :EOF
Always verify against a test directory before applying to real data.
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 directories.
Using a list of the directory-names, names only (/b) and directories only (/ad), tokenise the name using - as a delimiter and execute the rename using the token assigned to %%o (default is first token)

Parsing every file in submap recursively to output folder whilst maintaining relativity

I'm using the following batch code to convert all files in a certain directory if the target file doesn't already exist however I'm stuck at getting this to run through every submap and file within that (and keep the output relative with that submap)
So I currently use this:
for %%f in (input/textures/*.*) do ( IF NOT EXIST "ouput/textures/%%~nf.dds" (
"bin/ThempImageParser.exe" "input/textures/%%f" "ouput/textures/%%~nf.dds"
)
)
This works perfectly for a single folder (as was intended), it takes all the files in that specific folder, and passes them as arguments to my executable, which then outputs the file on the path of the second argument.
However this also contains a flaw (this is an additional problem though..) as it does not work if the output -folder- does not exist, so if possible I'd also want it to create the folder if need be.
I've found some batch documentation (I really don't have much experience with Batch) showing me a command called FORFILES and the /R parameter, however I couldn't adjust this so it'd keep the relative paths for the output too, it'd require string manipulation and I have no clue on how to do that.
So the result I'm after is something like this, it takes any file deeper than "input/textures/ for example:
input/textures/some/very/deep/submap/why/does/it/go/on/myfile.anyExtension
it should then take that file (and relative path) and basically change "input" with "output" and replace the file extension with .dds like this:
ouput/textures/some/very/deep/submap/why/does/it/go/on/myfile.dds
and pass those two strings to my executable.
#ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir\t w o"
SET "destdir=U:\destdir\wherever\something"
FOR /f "delims=" %%a IN ('xcopy /y /L /s "%sourcedir%\*"') DO (
SET "destfile=%%a"
SET "destfile=!destfile:*%sourcedir%=%destdir%!"
IF /i "%%a" neq "!destfile!" (
FOR %%m IN ("!destfile!") DO IF NOT EXIST "%%~dpm%%~na.dds" (
ECHO MD "%%~dpm"
ECHO "bin\ThempImageParser.exe" "%%a" "%%~dpm%%~na.dds"
)
)
)
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
First, perform an xcopy with the /L option to list-only the individual fullnames of files that would be copied by the xcopy.
Assign each name found from %%a to destfile, then remove all characters before the source-directoryname from that filename, and replace that string with the destination directoryname.
This will yield the destination name for the file (with the original extension). The only exception will be the very last output line, which is a count-of-files report. Since this line will not contain the source directoryname, the replacement will not take place, so %%a will be the same as !destfile! - so we eliminate that.
Now assign the destination filename to a metavariable so we can select its various parts, and if the filename made from the destination drive and pathname, the name part of the original file and .dds does not exist, then make the destination directoryname and execute the imageparser, providing the desired output filename.
Note that these last two are ECHOed instead of being executed for testing purposes. Remove the ECHOes to actually perform the command.
Note that / is a switch-indicator, \ is a directory-separator.
Note that MD will report an error if the directory already exists. Append 2>nul to the end of the md command to suppress that error message.

Batch wildcard strange behavior

I have a list of files that I'm looping through that match a certain size letter (A,B,C,D). The files are of the form ###T#####A###_# rev 1.dxf, where the rev 1 is only there some of the time, and A refers to the size, which is A, B, C, or D. When I try to loop through these in a set D.dxf or B.dxf, some A files are also found. I currently use the pattern ?????????A*.dxf, but would like to expand this to more file types without having to make multiple batch files. Interestingly, if I use the pattern TA*.dxf, the wildcard behaves normally.
Why does this happen, and how can I fix it while still being to catch files where the A may be at the beginning, end, middle, etc? If you need any clarification or extra information, feel free to ask.
Here is my relevant code:
FOR %%S IN (A,B,C,D) DO (
echo Converting size %%S. . .
FOR %%F in ("%filepath%\?????????%%S*.dxf") DO (
echo Converting %%~nxF to PDF, size %%S
SET %%S=!%%S! "%%~pF%%~nF.pdf"
"C:\Program Files\AutoDWG\AutoDWG DWG to PDF Converter\d2p.exe" /InFile %%~fF /OutFile %%~nF.pdf /Watermark %~dp0%%Swatermark.wdf /InConfigFile %~dp0%%S.ddp
)
echo:
echo Combining %%Ss. . .
pdftk !%%S! cat output "%filepath%\print\%%Ss.pdf"
echo Combined
echo:
)
EDIT: I'm running this on 32-bit Windows XP. Does this have anything to do with this thread? I will investigate when I get home.
EDIT 2: I've now figured out what the problem is. When I have several files with the same beginning characters, the 8.3 short names contain a hexadecimal number, which may match one of the letters I'm searching for. How can I discard short name matches in my for loop?
Your link to the Strange Windows DIR command behavior thread seems to be a good thought. From RBerteig's thorough answer: Wild cards at the command prompt are matched against both the long file name and the short "8.3" name if one is present.... Try next approach:
SETLOCAL enableextensions enabledelayedexpansion
:::
pushd %filepath%
FOR %%F in ("*.dxf") DO (
set "fname=%%~nF"
set "fmatch="
set "char04=!fname:~3,1!"
set "char10=!fname:~9,1!"
if /I "!char04!"=="T" (
FOR %%S in (A B C D) do if /I "!char10!"=="%%S" set "fmatch=!fname!"
)
if defined fmatch (
echo Converting %%~nxF to PDF, size !char10!
rem another stuff here
)
)
popd

Using a batch to sort through a complex of folders and sort any files with a specific string in their name to a specific directory?

So I have a collection of art from the internet; it is very large and spans an extreme amount of subdirectories under the main folder I keep it all under (entitled Uda). I've built up this collection over a period of about 4 years. In the most recent 2 years, I've been organising things I save by artist (most of this comes from the site DeviantArt if it matters). But I have 2 years' worth of files unsorted, all over the place and I'd like to sort them.
I figure this is an ideal time to practice some batch scripting, but... I've not the faintest idea where to start. Google hasn't been very helpful, it's too hard to explain what I want to do in one question, let alone find someone who has needed the same thing and been guided through it. Also, I'd honestly much prefer to pull apart and figure out an already-made script to understand it and learn from it (that's how I tend to learn best).
So can anyone help me? If you don't understand what I want to do:
I wish to make a script where I can input something (i.e. an artist's name) and have a folder made for it under a certain directory (no matter where the batch is being run from or the files drawn from) with the name of the term that was entered, and then all files under another directory with that term found and moved.
For the record, even if I weren't interested in batch scripting, I couldn't use Windows Explorer to search for them all then cut them because I disabled it (for personal reasons).
#ECHO OFF
SETLOCAL
:: Note that SPACES are significant in simple SET statements
:: Set relative or local root (start-point of subtree to scan)
:: Use normal then safemethod 1 then safemethod2 - all do the same thing
:: Note : from the prompt,
:: command /?
:: will generally show help...
SET relroot=c:\wherever
(SET relroot=c:\wherever)
SET "relroot=c:\wherever"
:: repeat for destination directory
SET "destdir=c:\destination"
::
:: Read Artist
:: Make sure ARTISTS has no existing value, then prompt for input
::
:again
(SET artist=)
SET /p artist="Artist ? "
::
:: Check for input, exit if none
:: Note :EOF is a special predefined label meaning "END OF FILE"
:: character case is generally insignificant
::
IF NOT DEFINED artist GOTO :eof
::
:: make a new directory
:: the 2>nul suppresses an error message like 'it already exists'
:: In quotes in case variables contain spaces
MD "%destdir%\%artist%" 2>nul
::
:: Now look for filenames containing the data entered
:: Note: here, the metavariable %%i IS Case-sensitive
:: >nul means 'don't show message like '1 file(s) moved'
FOR /f "delims=" %%i IN (
' dir /s /b /a-d "%relroot%\*%artist%*" '
) DO (
ECHO %%i
IF EXIST "%destdir%\%artist%\%%~nxi" (
ECHO Cannot MOVE "%%i" because "%destdir%\%artist%\%%~nxi" exists
) else (ECHO MOVE "%%i" "%destdir%\%artist%\%%~nxi" >nul)
)
GOTO again
Well, here's a starter script - assuming that artists' names are in the filename.
Most of the documentation is in-line.
Note that the ::... form of documentation is actually a broken-label and is inadvisable within loops and parenthesised code generally - use REM there. It is however easier to type and less intrusive
The FOR loop needs a little explanation: much of it can be deciphered with a bit of persistence from the documentation
for /?
from the prompt. But the heads-up is:
for /f reads a "file" line-by-line and applies each successive line to the metavariable after being tokenised between delimiters. You can specify the tokens by number counting from 1 and the delimiters are any characters appearing between the delims= and the closing quote. Default delimiters are [space],[tab],[comma],[semicolon] and default tokens is 1. "delims=" specifies that there are no delimiters, so the entire line is applied to the metavariable.
It's possible to use this facility on a data line like Wed. 07/11/2012 by using FOR/f "tokens=2,3,4delims=/ " %%i in... to apply 07 to %%i, 11 to %%j and 2012 to %%k - the tokens are Wed.,07,11 and 2012 when the line is tokenised using [either space or /] and the 2nd token is applied to the loop metavariable %%i, the third to %%j and so on through the list of token numbers. The special token "*" means 'the rest of the line following the highest-number token nominated'
AND.. a single-quoted "filename" is the output of a command. dir /s /b /a-d "%relroot%\*%artist%*" is the directorylist in /b basic form (filenames only) /s scan subdirectories /a-d but don't mention the war directorynames starting at %relroot% and having %artist% somewhere in the filename - all quoted in case spaces are present.
I wont write it for you but, but here is a list of roughly the things you have to achieve. Try looking for each of those and then combine them
input a name
create a directory with this name
find the files with this name
move found files to the directory
if you post code of what you are trying i'll gladly help you.

Windows .BAT to move all directories matching mask from dir A to dir B

I want to write a .BAT file to move all sub-directories (whose name matches a mask) of C:\WINNT\Temp to H:\SOMEOTHERPLACE.
So if my mask is ABC* then the directories :
C:\WINNT\Temp\ABC1
C:\WINNT\Temp\ABC2
C:\WINNT\Temp\ABC3
should be moved to
H:\SOMEOTHERPLACE
and everything else (including files, as opposed to directories, which match the mask) should not. I do want to move them and not copy.
Can anyone point me in the right direction ?
OK I've figured this out. If you write a movedirs.bat file containing the single line
for /d %%X in (%1) do move %%X %2\%%~nX
And then run it (with argument 1 being the mask for the directories I want to move and argument 2 being the directory I wish to move the directories to) as
C:\>movedirs.bat C:\WINNT\Temp\ABC* H:\SOMEOTHERPLACE\
It produces the effect I want.
The /d argument on the 'for' ensures that only directories are processed. The '~n' modifier on the %%X variable means that the original sub-directory name (as opposed to the entire path) is used as the target within the second command line argument.
Just for the sake of posterity in investigating this I did something similar with xcopy but then i would have had to get involved in deleting the source so for my purposes move works better but for the record here's the same idea wrapped around xcopy.
for /d %%X in (%1) do xcopy %%X %2\%%~nX /E /I
To process directories with as well as without extensions, for example "C:\MyDir*.MyExt" above command will need a combined (filename+extension) modifier "~nx":
for /d %%W in (%1) do xcopy %%W %2\%%~nxW /E /F /R /Y /I
[Comments are useless for structured answers so I'll repeat the comment here - with a couple of edits !]
Thanks for your answer but I've found that you can't use xcopy with a wildcard on the source. Or rather you can use wildcards but then you get only the directories being created without any content. So if you do this ...
H:\SOMEOTHERPLACE>xcopy C:\WINNT\Temp\ABC1 /E
... you'll get the the ABC1 directory copied to your current directory as you might reasonably expect but if you do this ...
H:\SOMEOTHERPLACE>xcopy C:\WINNT\Temp\ABC* /E
... you'll get each directory name present in C:\WINNT\Temp appearing in your current directory but those directories will be empty ! Please tell me I'm wrong but that's what I find !

Resources