Im trying to make a batch-file that creates random directories and create files in the folders. But I am unable to make it work.
This is what I have tried:
#echo off
cd "%userprofile%\desktop\Safe_Space"
md "%random%"
md "%random%"
md "%random%"
cd "*"
copy /Y NUL %random%.txt >NUL
This will create 10 folders with random names and 1 file within each folder with random names.
This will create a completely empty file in the created directories:
#echo off
setlocal enabledelayedexpansion
for /l %%i in (1,1,10) do (
set tempf=!random!
mkdir !tempf!
copy /y NUL !tempf!\!random! >NUL
)
Increasing/Decreasing the 10 in for /l %%i in (1,1,10) do ( will increased the number of folders and files. To add more files to folders, repeat echo nul > %random.txt or simply create another loop to create multiple files in the folders.
fsutil is a another option, but requires admin privileges, it will create a nul variable in the file.
#echo off
setlocal enabledelayedexpansion
for /l %%i in (1,1,10) do (
set tempf=!random!
mkdir !tempf!
fsutil file createnew !tempf!\!random! 1
)
This creates a new file, with some text, in this case the word nul will be written to file, but you can change that:
#echo off
setlocal enabledelayedexpansion
for /l %%i in (1,1,10) do (
set tempf=!random!
mkdir !tempf!
echo nul > !tempf!\!random!
)
You can create directories and files by using FOR, RANDOM and basic instructions.
RANDOM create a random number between 0 and 32767. You can control the range of RANDOM using bottomlimit and upperlimit, e.g. 1-1000:
SET /a bottomlimit = 1
SET /a upperlimit = 1000
Don't forget to use SETLOCAL ENABLEDELAYEDEXPANSION (check How do SETLOCAL and ENABLEDELAYEDEXPANSION work?) and inside the loop the !VARIABLE! notation instead of %VARIABLE%. The following example creates 5 directories and 10 empty files. You can change these values as you like, using
FOR /l %%i in (1,1,10) instead of FOR /l %%i in (1,1,2) creates 2 directories.
FOR /l %%i in (1,1,10) means a loop starts at 1, steps by 1, and finishes at 10.
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
REM creating 5 directories...
FOR /l %%i in (1,1,5) DO (
SET dirName=!RANDOM!
REM create a directory with random name
MKDIR !dirName!
CD !dirName!
REM creating 10 files...
FOR /l %%i in (1,1,10) DO (
REM create an empty file with random name
COPY NUL !RANDOM!>NUL
)
CD ..
)
The instruction COPY NUL !RANDOM!>NUL doesn't require administation privileges
the >NUL eliminates unwanted output to console
Related
I'm trying to create a .bat file that will copy all files that end with "XX" in three separate folders. I want it to put them all in one folder but add an incremental number to the end of the names (that way there aren't duplicate file names). After reading answers to my original question, I have written it again. But it still isn't copying everything because it gets duplicate filenames.
:: The setlocal line should put before the for loop:
setlocal EnableDelayedExpansion
set _a=0
for /D %%D in ("R:\SQL QUERIES\Mark\text append testing\*") do (
::Same as set /a _a=_a+1
SET /A _a+=1
echo !_a!
xcopy /Y /S "%%~D\*XX*" "R:\SQL QUERIES\Mark\conversion_scripts"
ren "R:\SQL QUERIES\Mark\conversion_scripts\*XX*" *!_a!
)
pause
This works:
:: The setlocal line should put before the for loop:
setlocal EnableDelayedExpansion
set _a=0
for /D %%D in ("R:\SQL QUERIES\Mark\text append testing\*") do (
::Same as set /a _a=_a+1
SET /A _a+=1
echo !_a!
xcopy /Y /S "%%~D\*XX*" "R:\SQL QUERIES\Mark\conversion_scripts"
ren "R:\SQL QUERIES\Mark\conversion_scripts\*XX" *X!_a!
)
I'm working on a project which works like that:
take a long video hard subtitled and cut it in a lot of smaller
scenes and where each scene lasts the time that it lasts the
subtitle to disappear
cut one only picture (maybe the first one or the last one) of each
segment of the original video and do it automatically
repeat (copy and paste) the picture extracted as many times as the
number of pictures that there are on each fragment that has been cut
on the original video
join everything
I have already achieved the point 1) and 2), now I'm trying to achieve point 3) and I need your help, please. Let's say that I have achieved point 2) with this batch script (that I call a.bat) :
pushd %1
if not exist newfiles\ (
mkdir newfiles
)
if not exist newfiles2\ (
mkdir newfiles2
)
:start
for %%F in (*.mov) do (
md "%%~nF"
echo "%%~nF"
ffmpeg -i %%F -r 1 -f image2 -qscale:v 2 "%%~nF\%%~nF_image-%%3d.png"
copy "%%~nF\%%~nF_image-001.png" ".\newfiles"
)
popd
So, I have this situation:
It means that in each folder there is a variable number of images that have been extracted from the *.mov files. Now, I want that the first image on the list of the images located on the relative folders is copied in another folder, as many times as many files there are in the same folder where it is. For example, let's take a look at this folder:
Here there are 4 images, right? I want to copy the first (or the last) image of the list for 4 times in this folder:
I would like that someone can help me to improve this batch script (that I call b.bat)...
#echo off
setlocal enabledelayedexpansion
set count=0
for %%x in (*.png) do set /a count+=1
echo %count%
FOR %%F IN (*.png) DO (
set filename=%%F
goto tests
)
:tests
echo "%filename%"
for /l %%i in (1,1,%count%) do copy %filename% ..\newfiles2\%%i.png
endlocal
pause
because I figured out that it works only if I put a copy of it in every/each folder,but then I have to enter in each folder to run it,wasting a lot of time. Let's say that I want to run it in the folder where all the others folders are located. How can I modify the script to do so ? This is what happens if I run it on the "root" folder :
EDIT : thanks to the suggestion of #AlexP I modified the script like this :
#echo off
setlocal enabledelayedexpansion
set count=0
for /d %%d in (render*) do set /a count+=1t
echo %count%
pause
for %%f IN ("%%~d\*") do (
set filename=%%F
goto tests
)
:tests
echo "%filename%"
for /l %%i in (1,1,%count%) do copy %filename% .\%%i.png
endlocal
pause
now the var "count" has value 4,but this is wrong. the value that i need is inside each folder that starts with the word render* ; so,since I have 4 pics inside the "render00003211" folder the value is 4; 5 pics under "render00003266" the value is 5 and so on..
UPDATE : I've ordered sequentially the names of the pictures by placing this script inside the Duplicates folder...
#echo off
setlocal enabledelayedexpansion
mkdir pics
copy *.png .\pics
del *.png
for /d /r %%a in (%1\*.*) do (
set /a counter=0
for %%b in ("%%a\*.*") do (
set /a counter += 1
set zcounter=0000!counter!
set source="%%~fb"
set target="pic!zcounter:~-4!%%~xb"
echo Renaming !source! to !target!
ren !source! !target!
)
)
for /l %%i in (1,1,%count%) do copy %filename% %somewhere%
From for /?:
FOR /L %variable IN (start,step,end) DO command [command-parameters]
The set is a sequence of numbers from start to end, by step amount. So (1,1,5) would generate the sequence (1 2 3 4 5) and (5,-1,1) would generate the sequence (5 4 3 2 1).
Here is a script which implements what I understand to be the requirements:
#echo off
:: This script will visit each subdirectory of the directory from where it is
:: run; it will take the first file found in that subdirectory and copy it to
:: the directory ..\Duplicates as many times as there are files in that
:: subdirectory; the names of the copied files are taken from the name of the
:: subdirectory with a numeric suffix appended, and have the extension of the
:: copied file. If ..\Duplicates does not exist then it is created.
setlocal
echo Working in directory "%CD%"
if not exist ..\Duplicates mkdir ..\Duplicates
if not exist ..\Duplicates\. (
echo Destination ..\Duplicates does not exist, and I cannot create it.
exit /b
)
for /d %%d in (*) do call :duplicateDir "%%~d"
exit /b
:duplicateDir
echo * "%~1"
set COUNT=0
set "SUBNAME=%~n1"
set SUBFILE=&
set SUBEXT=&
for %%f in ("%~1\*") do call :duplicateFile "%%~f"
echo "%SUBFILE%" copied %COUNT% times
exit /b
:duplicateFile
if not defined SUBFILE set "SUBFILE=%~1"
if not defined SUBEXT set "SUBEXT=%~x1"
set /a COUNT=COUNT+1
echo copy "%SUBFILE%" "..\Duplicates\%SUBNAME%-%COUNT%%SUBEXT%"
:: copy "%SUBFILE%" "..\Duplicates\%SUBNAME%-%COUNT%%SUBEXT%" >nul
exit /b
Note that instead of actually doing the copying the script displays the command which would be executed. When you are happy with it, comment out the echo copy and uncomment the copy.
Under the path U:\test\0014* I have 99 folders and each of them has respectively 2 subfolders MASTER and DERIVATIVE_COPY. With a following script I try to count the number of PDFs in MASTER folder. If there are only one .pdf file there I want to copy it to DERIVATIVE_COPY folder. IF there are 0 or >1 .pdf in MASTER I want only to show the number of them. This operation should be done for each of the 99 folders.
#echo off
setlocal enabledelayedexpansion
for /R U:\test\0014\*\MASTER %%i in (*.pdf) do (
set /a anzahl+=1
)
if !anzahl! EQU 1 ( echo !anzahl! )
if NOT !anzahl! EQU 1 ( echo !anzahl! )
pause
#ECHO OFF
SETLOCAL enabledelayedexpansion
SET "sourcedir=U:\sourcedir"
for /f %%i in ('dir /ad /s/b "%sourcedir%\master*"') do IF /i "%%~nxi"=="MASTER" (
SET /a found=0
FOR %%x IN ("%%i\*.pdf") DO SET /a found+=1
IF !found!==1 (
XCOPY /y "%%i\*.pdf" "%%i\..\derivative_copy\" >nul
) ELSE (
ECHO !found! .pdf files found IN "%%i"
)
)
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
First, execute a dir to get a directory-list of the "files" names that start master in the specified tree. Use /ad to select only the directory-names. Accept only those names where the "name+extension" is master (disregarding case)
For each directory-name found, set found to 0 then increment found for each .pdf file found in the directory %%i.
If the resultant count in found is 1, xcopy the file found to the destination subdirectory (which conveniently creates the subdirectory if it doesn't already exist), using /y to overwrite any existing file of the same name and >nul to make the process silent.
Otherwise, report the directoryname and count of files.
I'm having a bit of trouble with a FOR DO command in a .BAT file I'm working on for work.
Here is the entire code I'm working with
SET parent="%~dp0"
SET GroomedDir="%~dp0Groomed\"
XCOPY /s/e/y Groomed %parent%NewGroomed\
CD NewGroomed
setlocal enabledelayedexpansion
FOR %%i in (IMG_*.jpg) DO (
SET OldName=%%i
SET ImgNumber=!OldName:~4,-4!
SET DBLookup=FINDSTR !ImgNumber! Database.txt
!DBLookup! > return.txt
FOR /F "tokens=1-5 delims=|" %%J in (return.txt) do (
REN !OldName! "%%K_%%L.jpg"
MKDIR %%M\%%N
MOVE "%%K_%%L.jpg" %%M\%%N
)
)
del return.txt
endlocal
cd ..
ren Groomed "Groomed Backup"
ren NewGroomed Groomed
The trouble come in lines 12-14 (I put in line separators). I can't seem to put the variable %DBLookup% into the FOR command, and am forced to use a placeholder text file instead. It works, in the end, but wouldn't it be better to save myself the write to return.txt operation, and the read return.txt operation?
For context, return.txt contains a single line from of text like this:
115525|Last_First|5233|8|Teacher
I use the FOR command because it allows me to delimit using the pipe character, or whatever else, and output to %%J %%K %%L %%M and %%N variables.
Any help or advice for this relative newcomer is much appreciated!
Here's my code with my comments:
REM THESE FOUR LINES:
REM 1) SET A VARIABLE FOR THE PARENT DIRECTORY LOCATION,
REM 2) SET A VARIABLE FOR THE GROOMED DIRECTORY,
REM 3) COPY THE GROOMED DIRECTORY TO "NEWGROOMED\",
REM 4) CHANGE THE LOCATION TO BE WORKING ENTIRELY WITHING NEWGROOMED\
SET parent="%~dp0"
SET GroomedDir="%~dp0Groomed\"
XCOPY /s/e/y Groomed %parent%NewGroomed\
CD NewGroomed
REM THIS FOR LOOP LOADS ALL JPGS IN THE \NEWGROOMED\ DIRECTORY THAT BEGIN WITH THE STRING, "IMG_"
setlocal enabledelayedexpansion
FOR %%i in (IMG_*.jpg) DO (
SET OldName=%%i
REM THIS LINE COPIES THE OLD NAME MINUS THE FIRST FOUR CHARACTERS, "IMG_", AND MINUS THE EXTENSION (LAST 4 CHARS)
SET ImgNumber=!OldName:~4,-4!
REM THESE NEXT TWO LINES LOOK UP OUR IMAGE NUMBER IN DATABASE.TXT AND RETURN THE ENTIRE LINE TO A NEW FILE CALLED RETURN.TXT
SET DBLookup=FINDSTR !ImgNumber! Database.txt
!DBLookup! > return.txt
REM NOW WE PARSE RETURN.TXT USING PIPE DELIMITERS INTO THE VARIABLES J,K,L,M,N (ID,Name,IMG#,Grade,Homeroom)
FOR /F "tokens=1-5 delims=|" %%J in (return.txt) do (
REN !OldName! "%%K_%%L.jpg"
MKDIR %%M\%%N
MOVE "%%K_%%L.jpg" %%M\%%N
)
)
del return.txt
endlocal
cd ..
ren Groomed "Groomed Backup"
ren NewGroomed Groomed
Overall, my goal is to begin with a folder, "Groomed," with a bunch of images titled as such: IMG_####.jpg.
My batch file will:
1) create a backup of the entire starting directory
2) rename each image according to the database.txt file
3) move each renamed image into a new grade/teachername folder
I am starting with a file, (database.txt) that comes to me from another employee. The file is a plain list for each student in the following format: student id|lastname_firstname|image#|grade#|teachername.
As i mentioned. The file works perfectly, but since I'm new to batch files I was feeling like it might be dumb of me to write to a throwaway file just to save a string and then delete it. That's what variables are for, but I was having a hard time getting that variable to pass into the FOR command.
sample of Database.txt
659968|Saperstein_Ryan|4603|7|Hallock
015520|Qian_Emily|2528|7|Hallock
528852|Rizzo_Jason|4618|7|Krukowski
and a few filenames I'm starting with:
IMG_2528.jpg
IMG_4544.jpg
IMG_7044.jpg
IMG_6880.jpg
IMG_4839.jpg
Edit:
A first bunch by parsing database.txt first and then compare by using if exist. The second is by comparing variables
code:
rem create a sample of the following example
rem :: student id|lastname_firstname|image#|grade#|teachername
rem :: The common points are only in the first 3 jpg
copy nul IMG_4603.jpg
copy nul IMG_2528.jpg
copy nul IMG_4618.jpg
copy nul IMG_4619.jpg
copy nul IMG_4620.jpg
copy nul IMG_4630.jpg
(
echo 659968^|Saperstein_Ryan^|4603^|7^|Hallock
echo 015520^|Qian_Emily^|2528^|7^|Hallock
echo 528852^|Rizzo_Jason^|4618^|7^|Krukowski
echo 528817^|Rizzo_Jas17^|4617^|7^|Krukows17
echo 528816^|Rizzo_Jas16^|4616^|7^|Krukows16
)>sample.txt
rem :: type sample.txt
rem :: pause
Method #1
#echo off
setlocal enabledelayedexpansion
for /f "tokens=1-5 delims=|" %%a in (sample.txt) do (
set "student_id=%%a"
set "student_name=%%b"
set "student_image=%%c"
set "student_grade=%%d"
set "student_teacher=%%e"
rem :: echo !student_name!_!student_image!.jpg
if exist "IMG_!student_image!.jpg" (
rem :: remove echo in the following lines if it's okay.
echo:
echo ren "IMG_!student_image!.jpg" "!student_name!_!student_image!.jpg"
echo mkdir "!student_grade!\!student_teacher!"
echo move "!student_name!_!student_image!.jpg" "!student_grade!\!student_teacher!"
)
)
Method #2
#echo off
setlocal enabledelayedexpansion
for %%i in (IMG_*.jpg) do (
set "OldName=%%~i"
set "image_number=!OldName:~4,-4!"
rem :: echo image_number: !image_number!
for /f "tokens=1-5 delims=|" %%b in (
'findstr !image_number! sample.txt'
) do (
set "student_id=%%a"
set "student_name=%%b"
set "student_image=%%c"
set "student_grade=%%d"
set "student_teacher=%%e"
if "!student_image!"=="!student_image!" (
rem :: remove echo in the following lines if it's okay.
echo:
rem :: echo !image_number! = !student_image!
echo ren "IMG_!student_image!.jpg" "!student_name!_!student_image!.jpg"
echo mkdir "!student_grade!\!student_teacher!"
echo move "!student_name!_!student_image!.jpg" "!student_grade!\!student_teacher!"
)
)
)
output:
ren "IMG_2528.jpg" "Qian_Emily_2528.jpg"
mkdir "7\Hallock"
move "Qian_Emily_2528.jpg" "7\Hallock"
ren "IMG_4603.jpg" "Saperstein_Ryan_4603.jpg"
mkdir "7\Hallock"
move "Saperstein_Ryan_4603.jpg" "7\Hallock"
ren "IMG_4618.jpg" "Rizzo_Jason_4618.jpg"
mkdir "7\Krukowski"
move "Rizzo_Jason_4618.jpg" "7\Krukowski"
I have to create a couple of thousand directories.
The directories look like this: 10P001 being YEAR/P,S,L,R,F/Numberfrom001to600
the letters are not systematic, so i have to write them for every folder.
my script until now looks like this, but cmd doesnt like the for loop.
#echo off
setlocal enabledelayedexpansion
set /p jahr=Welches Jahr?
set /p anzahl=Wieviele Projekte?
set looop=%anzahl+1000
for /l %%x in (1001, 1, looop) do (
set nummer=%%x
set /p welches=P1 S2 L3 R4 F5 nichtexistent6?
if %welches%==1 mkdir %jahr%P!nummer:~-3!
if %welches%==2 mkdir %jahr%S!nummer:~-3!
if %welches%==3 mkdir %jahr%L!nummer:~-3!
if %welches%==4 mkdir %jahr%R!nummer:~-3!
if %welches%==5 mkdir %jahr%F!nummer:~-3!
if %welches%==6 echo "nicht existent"
)
pause
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /f "tokens=1,2delims= " %%a IN (q28608207.txt) DO (
FOR /l %%x IN (1001,1,1011) DO (
SET seq=%%x
ECHO(MD %%a%%b!seq:~-3!
)
)
GOTO :EOF
I used a file named q28608207.txt containing this data for my testing.
10 P
10 S
The routine reads the two fields from the file as %%a and %%b, then for a loop varying %%x from 1001 by 1 to 1011 (it can of course be 1600 - 1011 just proves the point), copy %%x to a temporary veriable (because substringing can't be applied to the metavariable %%x) create a directory named %%a%%b and the last 3 characters of the temporary variable.
Note that the setlocal enabledelayedexpansion command enables the use of !var! (accessing the value of var as it varies)
The required MD commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MD to MD to actually create the directories. Append 2>nul to suppress error messages (eg. when the directory already exists)
To create a file containing the required numbers:
#echo off
setlocal enabledelayedexpansion
set /p jahr=Welches Jahr?
set /p anzahl=Wieviele Projekte?
set looop=%anzahl+1000
(
for /l %%x in (1001, 1, looop) do (
set nummer=%%x
echo %jahr%P!nummer:~-3!
)
)>J%jahr%.txt
This would produce a list (for jahr=14,say) in J14.txt
14P001
14P002
14P003
and then all you need do is edit the file (use notepad, not a word-processor) to replace the "P" with whatever letter is required. delete any line where no directory is required.
The resultant file could then be processed to directories by using
#ECHO OFF
SETLOCAL
FOR /f %%a IN (J14.txt) DO (
ECHO(MD "%%a"
)
GOTO :EOF
my solution for now (i know its worse than bad habit, but it works and will save me a lot of time (or at least my company some money)):
#echo off
setlocal enabledelayedexpansion
set /p jahr=Welches Jahr?
set /p anzahl=Wieviele Projekte?
set /a looop=%anzahl%+1000
set /a count=1001
:LoopStart
set /p welches=P1 S2 L3 R4 F5 nichtexistent6?
if !welches!==1 mkdir %jahr%P!count:~-3!
if !welches!==2 mkdir %jahr%S!count:~-3!
if !welches!==3 mkdir %jahr%L!count:~-3!
if !welches!==4 mkdir %jahr%R!count:~-3!
if !welches!==5 mkdir %jahr%F!count:~-3!
if !welches!==6 echo "nicht existent"
set /a count=%count%+1
if %count% leq %looop% (goto LoopStart) else (goto:eof)
pause