Choose Random text file in batch - batch-file

is it possible to make a batch file choose a totally random text file from within a specified folder
and can somebody help me make it?
example
lets say that i got a folder located here: C:\Workstation\Jobs
and in that folder there is maybe 10-20 .txt files at a time
the goal here is to make that batch file check the folder and then choose a random file and output the choosen file to a variable

#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f %%a IN (
'dir /b /a-d "%sourcedir%\*.txt"^|find /i /c ".txt" '
) DO SET /a selection=1 + (%RANDOM% %% %%a)
FOR /f "tokens=1*delims=:" %%a IN (
'dir /b /a-d "%sourcedir%\*.txt"^|findstr /n /i ".txt" '
) DO IF %%a==%selection% SET filename=%%b
ECHO selected %filename%
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
find /c counts the number of files found by the dir command and the for assigns the count to %%a. selection is then assigned to 1+(randomnumber mod filecount) giving 1..filecount.
findstr /n outputs the name of each file found by the dir command, prefixed by a sequential number : %%a will be assigned the number (token before the : and %%b the filename (afther the first delimiter where delims is :)
When the line number matches selection, filename is assigned the filename found.

In the case of the said folder only containing text files, you'd need the following:
a list of folder contents in some sort of array (dir)
count the amount of files (for loop)
pick a random number between 0 and the amount of files (%RANDOM%*amount_of_files/32768)
output the matching filename (in the array) to the variable you want
Hope this pushes you in the right direction :-)
sources:
http://ss64.com/nt/syntax-random.html
How to loop through files matching wildcard in batch file
Create list or arrays in Windows Batch

Related

Delete string in multiple files in directory with cmd

:-)
I'm very new to cmd-commands and .bat-stuff, so would be grateful if any of you could help me with a problem.
So...I have a folder with 116 .txt files.
All these .txt files contain lines starting with a "#" and some other lines starting with "---".
I figured that findstr /v /L /C:"#" test.txt > test2.txt works in creating a new file without any lines that contain "#"
Now my question, is it possible to write something like findstr /v /L /C:"#" & "---" *.txt > *.txt ?
The goal is that each existing file is overwritten and all lines containing either "#" or "---" are removed.
Glad for any help!
Cheers,
Dyz
#ECHO OFF
SETLOCAL
rem The following setting for the source directoryis a name
rem that I use for testing and deliberately include names which include 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\t w o"
FOR /f "delims=" %%w IN ('dir /b /a-d "%sourcedir%\*.txt"') DO FINDSTR /v /L /c:"#" /c:"---" "%sourcedir%\%%w">"%sourcedir%\tempfile"&MOVE /y "%sourcedir%\tempfile" "%sourcedir%\%%w" >nul
GOTO :EOF
The meat of the matter is the for/f line, obviously.
Run dir /b to obtain a list of the filenames. /a-d excludes directorynames. This list is built in memory first, as the .txt files are being replaced - this ensures that the files are only "listed" once.
The for /f "delims=" reads that list and assigns each line-contents (filename+extension only) to %%w. The delims= ensures that filenames containing spaces are properly processed.
Then execute the findstr, which can take multiple /c: arguments to or the strings.
[I haven't tried it, but FINDSTR /v /L "# ---" "%sourcedir%\%%w" should produce identical processing]
The output of the findstr is directed to a temporary filename (I chose to put it in the source directory, but it could be anywhere with any name) and then the temporary file is moved over the original with the 1 file moved message suppressed by a >nul.
As always, test first on a copied sample.

How to remove digits from beginning of filename?

I need to rename a filename like this 7612372 filename 50x50.jpg into this filename 50x50.jpg, removing all digits at the beginning of the filename.
The number of digit can be variable.
I need to integrate this into an existing batch file run from the Windows command prompt.
If the format of the filename would be the same for all the files in the folder, then you can try:
#echo off
for /F "delims=" %%A IN ('dir /b /A-D') do (
for /F "tokens=2-3" %%B IN ("%%A") do (
ren "%%~fA" "%%B %%C"
)
)
This is the shortest way, but not the most accurate one. It is unsecure, because if the filename contains spaces, the file will be rename incorrectly. I suggest the following code for the task:
#echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%A IN ('dir /b /A-D') do (
set filename=%%A
for /F "tokens=1" %%B IN ("%%A") do (
ren "%%~fA" "!filename:%%B =!"
)
)
which is more accurate and renames all files correctly only if they have the format mentioned in the beginning.
#echo off turns command-echoing off.
setlocal EnableDelayedExpansion enables delayed expansion. We use it only here, as we have to access variables inside a for loop which is a code block. You must use delayed expansion always inside these code blocks.
Now we make a for loop to parse the output (/F) of the dir /b /A-D command which lists all items in current working directory (%cd%), excluding directories (/A-D).
We need to set a variable here with the filename. We could use the variable name of the loop (%%A), but variables have an advantage: %var:search=replace%, or even !var:search=replace! which we need here.
Now we make another for loop to parse a string (/F): the filename (%%A). We need to access the first token to substract it later. We don't really need to specify it here, but it is good to make it clearer.
We rename files now: %%~fA is the full path where filename currently processed is and !filename:%%B =! means to take filename environment variable, search for string "%%B " (first part of filename [digits] and a space) and replace it with an empty string; actually nothing!
An easier solution is to use
all digits and space as delims and
tokens=*
:: Q:\Test\2019\01\06\SO_54054587.cmd
for /F "delims=" %%A in (
'dir "* *" /A-D-H /B 2^>nul'
) do for /F "tokens=* delims=0123456789 " %%B in (
"%%A"
) do ren "%%A" "%%B"
this will remove all leading delimiters while not splitting the remainder of the file name.
Like the other answers this will not account for the shorted file name already being present.
Your question is not specific enough for us to provide a solution, you really need to provide the section of code into which you wish this to be integrated.
This one expects only one file, as in your question, and that file must be named in the format you've indicated, i.e. the required part is separated from the non-required part by a space:
#Set "name=7612372 filename 50x50.jpg"
#Ren "%name%" "%name:* =%"
[Edit /]
I have noted from your comments that you were indeed looking to parse several files and those files did not match the naming scheme you provided in your question.
Here therefore is an updated potential solution based on those changed parameters.
#For %%A In (*.*) Do #For /F "Tokens=* Delims=0123456789 " %%B In ("%%A") Do #Ren "%%~A" "%%B"
Apologies to LotPings, who I've noticed has posted a very similar method/solution
It's very simple with the basic DOS command rename.
7612372 filename 50x50.jpg
If this is your sample file in the folder, it contains 7 digits and 1 blank space. Totally 8 characters.
We can do this by simply running this command on the particular folder
rename "*.mp3" "////////*.mp3"
each / represents a character you want to remove. That's it.
I suggest following batch code for this task:
#echo off
for /F "delims=" %%A in ('dir "* *" /A-D-H /B 2^>nul') do for /F "tokens=1*" %%B in ("%%A") do ren "%%A" "%%C"
pause
The command FOR runs with cmd.exe /C (more precise %ComSpec% /C) in a separate command process in background the command line:
dir "* *" /A-D-H /B 2>nul
DIR outputs to handle STDOUT of this background command process
just the names of all non-hidden files because of option /A-D-H (attribute not directory and not hidden)
in bare format because of option /B without file path
matching the wildcard pattern * * which matches any file name with at least one space inside
in current directory which can but must not be the directory of the batch file.
DIR would output an error message to handle STDERR if it can't find any directory entry matching these criteria. This error message is redirected to device NUL to suppress it.
Read the Microsoft article 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.
FOR captures all lines output to handle STDOUT of started command process and processes those lines after started cmd.exe terminated itself. It is very important for this file renaming task that FOR runs on a list of file names captured before doing the file renames as otherwise the directory entries would change while FOR is accessing them. For that reason for can't be used directly in this case because of for would process the list of * * directory entries while this list changes on each successful file rename. The result would be files not renamed or renamed multiple times or even an endless running loop depending on file system (NTFS or a FAT file system like FAT32 or ExFAT).
FOR with option /F ignores empty lines which do not occur here. FOR ignores also lines starting with a semicolon because of end of line option eol=; is the default. But all lines output by DIR should start with a number and for that reason the default end of line definition can be kept for this task.
FOR with option /F splits up a line by default to substrings using normal space and horizontal tab as delimiters and assigns just first space/tab separated string to specified loop variable. This line splitting behavior is not wanted here in outer FOR loop because loop variable A should hold complete file name with all spaces. Therefore delims= is used to define an empty list of delimiters to disable the line splitting behavior. Safer would be "delims= eol=" which defines also no end of line character.
The file name assigned to loop variable A is referenced with %%A as string in inner FOR loop which splits up the file name into two substrings (tokens). The first substring is the number assigned to specified loop variable B. The second substring after first sequence of spaces (tabs not possible in a file name) is assigned without any further splitting to next loop variable C according to ASCII table. In other words on file name 7612372 filename 50x50.jpg loop variable B holds 7612372 and filename 50x50.jpg is assigned to loop variable C.
The command REN renames the file by referencing complete file name as assigned to loop variable A to the part after first sequence of spaces as assigned to loop variable C.
The command PAUSE at end is added to see the error message output by command REN if renaming a file failed. There is nothing output except the prompt by PAUSE on all files could be renamed successfully.
The batch code can be enhanced further by using FINDSTR as filter to make sure that a file to rename starts really with one or more digits up to first space by using this code:
#echo off
for /F "delims=" %%A in ('dir "* *" /A-D-H /B 2^>nul ^| %SystemRoot%\System32\findstr.exe /R /C:"^[0123456789][0123456789]* "') do for /F "tokens=1*" %%B in ("%%A") do ren "%%A" "%%C"
pause
One more variant for renaming a file with name 03T30 NAME T ALL 40X40X2 - Copy.JPG to T30 NAME T ALL 40X40X2 - Copy.JPG:
#echo off
for /F "delims=" %%A in ('dir /A-D-H /B 2^>nul ^| %SystemRoot%\System32\findstr.exe /R "^[0123456789][0123456789]*"') do for /F "tokens=* delims=0123456789 " %%B in ("%%A") do ren "%%A" "%%B"
pause
DIR outputs the names of all non-hidden files in current directory. This output is redirected as input for FINDSTR which checks if the file name starts with one or more digits. Only those file names are output to STDOUT of background command process to be processed next by FOR.
The inner FOR interprets all digits and space character as string delimiters because of delims=0123456789  and assigns everything after first sequence of digits or spaces to loop variable B because of tokens=*. So loop variable B holds filename 50x50.jpg with 7612372 filename 50x50.jpg assigned to A and T30 NAME T ALL 40X40X2 - Copy.JPG for file name 03T30 NAME T ALL 40X40X2 - Copy.JPG.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
dir /?
echo /?
findstr /?
for /?
pause /?
ren /?
PS: I recommend the usage of the shareware file manager Total Commander which has a built-in multi-rename tool for renaming files and folders for people with no coding experience. Download, install and start Total Commander, navigate to the folder containing all these files, press Ctrl+A to select the files, press Ctrl+M to open multi-rename tool window and the rest is self-explaining. If you need nevertheless help, press key F1 to open the help page for multi-rename tool.

Batch file to Move files based on part of filename, to folder based on part of folder name

Found a pyhton solution here, but I need a batch file-based solution.
Have many files:
SSP4325_blah-blah-blah.xml
JKP7645_blah.xml
YTG6457-blah-blah.xml
And folder names that contain a piece of the file name:
RefID - SSP4325, JKP7645, GHT1278, YRR0023
RefID - YTG6457
I'm looking for a batch solution which would read a portion of the file name at the front (before either the first dash or underscore) and then move that file into the folder where the front of the filename exists as part of the folder name.
So in the above examples, the first two files (SSP4325 and JKP7645) were moved into the first folder because it contained it contained that text as part of the folder name.
The third file would be moved into the second folder.
I have hundreds of files and 63 folders. So I'm hoping to be able to automate.
Can't use Powershell or Python due to limitations of the environment. So hoping for a batch file approach.
Thanks. Sean.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*.xml" '
) DO (
FOR /f "tokens=1delims=_-" %%b IN ("%%a") DO (
FOR /f "delims=" %%d IN (
'dir /b /ad "%destdir%\*%%b*" '
) DO (
ECHO(MOVE "%%a" "%destdir%\%%d\"
)
)
)
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
The required MOVE commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MOVE to MOVE to actually move the files. Append >nul to suppress report messages (eg. 1 file moved)
After establishing the directories, the outer loop puts the filename in %%a, the next loop gets the first part of that name, up to but not including the first - or _ (the delims specified) into %%b.
The inner loop finds the target directory containng %%b in the destination directory and constructs an appropriate move line.
This solution review the folders just one time and store they in an array, so this method should run faster.
#echo off
setlocal EnableDelayedExpansion
rem Process the folders
set i=0
for /D %%a in (*) do (
rem Store this folder in the next array element
set /A i+=1
set "folder[!i!]=%%a"
rem Separate folder in parts and store the number of the array element in each one
for %%b in (%%a) do set "part[%%b]=!i!"
)
rem Process the files
for %%a in (*.xml) do (
rem Get the first part of name
for /F "delims=-_" %%b in ("%%a") do (
rem If such a folder exists...
if defined part[%%b] (
rem Get the number of the corresponding array element and move the file
for %%n in (!part[%%b]!) do ECHO move "%%a" "!folder[%%n]!"
) else (
echo No folder exists for this file: "%%a"
)
)
)
This method have also several advantages: you may check if a certain folder does not exists, or get the number of files moved to each folder, etc. If you are not interested in these points, just remove the if command and make the code simpler...
An explanation of array management in Batch files is given at this answer.

Random renaming all .exe files in a folder using batch

What I want to accomplish is to rename all the .exe that I have in a folder.
Sample of random name should be "589uday5xpsa9iz.exe"
I would appreciate any help I can get on this, I have been trying to figure it out for a couple of days now.
Try this :
#echo off
setlocal enabledelayedexpansion
:://The string length of the output
set $Lcode=16
set $#=#
:://The char Map
set $l="#0=0" "#1=a" "#2=B" "#3=c" "#4=d" "#5=E" "#6=f" "#7=g" "#8=H" "#9=I" "#10=j" "#11=K" "#11=1" "#13=2" "#14=3" "#15=4" "#16=5"
:://Evaluating the char MAP
for %%a in (%$l%) do set %%~a
:://Looping in the directory for .exe files
for /f "delims=" %%x in ('dir /b/a-d "*.exe"') do (
for /l %%a in (0,1,%$Lcode%) do (
call:rand
)
ECHO ren "%%x" !$Fstring!.exe
set $Fstring=
)
pause
exit/b
:://Getting the random Char
:rand
set /a $n=!random!%%17
set $Fstring=!$Fstring!!#%$n%!
I made a char MAP of just 15 char but you can increase it with all the char (up and downcase + number). If you do it. You have to increase the value in !random!%%17
with the value of the total CHAR map(+1).
You can increase the length of the random string by changing the value in the variable : $Lcode (16) in this example.
The output :
ren CnpjSdee.exe 2aHg5I22EBBE2ff5.exe
ren DbatchCnpj.exe EIIg2E54aHHIEgfHE.exe
ren NTStreamColor.exe jg03f3dIfBfIfHj2.exe
ren savedialog.exe EgfdajIcdc2cf03E.exe
Press any key to continue. . .
If it's OK Remove the ECHO to realy rename the files.
this is a simple batch that will work from within the folder that contains the files to be renamed you could make a shortcut to use it from the desk top. use copy and paste for long names. C:\Documents and Settings\Owner\Desktop\New Folder\Rename.bat (file = Rename.bat) don't use the whole path.
#echo off
title Rename Bat
echo This bat must be in the folder that
echo contains the files to be renamed.
:begin
echo Enter File Name
set /p old=
echo Enter New Name
set /p new=
ren "%old%" "%new%"
echo File Renamed
ping -n 3 127.0.0.1 >NUL
goto begin
hope this works for you.
a much simpler approach ... try a for loop that cycles through all files in that folder and renames them one at a time giving each a unique number ...
#echo off
for /L %%n in (1 1 %random%) do (
for %%a in (*.exe) do (
rename "%%a" "%%a_%%n.exe"
)
)
so %%a represents all the files in that folder and %%n represents the unique number that is going to be assigned to each file in the for body separated with _ symbol
to use this batch file you have to place it in the folder containing your .exe files
this would rename files to original name_1 then original name _2 and so on if you want it to be completely random use only %random% in bracket of the first for loop and do away with the iteration "1" (see below) also at the renaming part do away with %%a to omit the original name of file so that you remain with only random numbers also see below e.g
#echo off
for /L %%n in (%random%) do (
for %%a in (*.exe) do (
rename "%%a" "%%n.exe"
)
)
hope this helps .....

What is the DOS search pattern expression to find files named "Main" with any integer extension?

I have a program that generated unknown numbers of files with integer extension as follows.
I want to append .eps to each. How to do this in a DOS batch file?
I cannot use the following because I don't know the search expression.
for %%x in (Main.<what>) do rename "%%x" "%%x.eps"
Note: Any files having the same name with non-integer extension must be left as is.
setlocal EnableDelayedExpansion
for %%x in (Main.*) do (
set ext=%%~Xx
set /a num=!ext:~1!
if !num! gtr 0 rename "%%x" "%%x.eps"
)
First SET get just the extension of file name, including the dot (with ~X). Second SET /A try to convert the extension (without the dot with :~1) to number. If it is really a number (greater than zero) do the rename.
This should loop through the directory. Here is the explanation on how it works:
tokens = 1-2 means we only care about the first and second part of the file name.
delims = . means to split the tokens on the . in the file name.
dir /b means to only list the files, don't show any of the . or .. that is normally shown in the dir command. You need to put the directory in there or run from the same file directory.
LSS a char will always return GREATER THAN, that's how this works. I picked 9999, you can pick whatever.
Finally, it takes the first part of the file name (%%A) and then the extension (%%B) then renames to first part of the file name (%%A) with the eps extension.
for /f "tokens=1-2 delims=." %%A in ('dir /b') do if %%B LSS 9999 rename %%A.%%B %%A.%%B.eps
Put this in your batch file and run it.
Note: You can't rename to the same filename, so I used %%A.%%B.eps.

Resources