Want to make a batch file from a folder of 30,000 files from let's say C:\Users\NAME\Desktop, that will create a folder named "1", put 500 files in, no matter the name of the file, and then loop naming the next "2", until all 30,000 are in folders of 500 files each.
Thanks in advance for the help :)
#ECHO OFF
SETLOCAL
rem The following settings for the source directory and destination directory are names
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"
SET "destdir=u:\your results"
PUSHD "%sourcedir%"
ECHO sd=!sourcedir!
FOR /f "tokens=1*delims=:" %%b IN (
'dir /b /a-d * png *.doc^|findstr /n "."'
) DO (
SET /a subdir=1+(%%b / 7^)
FOR /f "tokens=2delims==" %%e IN ('set subdir') DO (
ECHO MD "%destdir%\%%e" 2>NUL
ECHO MOVE "%%c" "%destdir%\%%e\"
)
)
popd
GOTO :EOF
Always verify against a test directory before applying to real data.
I used a limit of 7 for testing. Modify as you will
Required md and move commands are merely echoed for verification. remove the echoes to activate after testing.
Found this from Compo, sorry didn't reference it!
#Echo Off
If /I Not "%__CD__%"=="%~dp0" PushD "%~dp0" 2>Nul||Exit/B
SetLocal EnableDelayedExpansion
Set "DirN=-1"
:Check_DirN
Set/A "DirN+=1"
If Exist "%DirN%" GoTo Check_DirN
Set "limit=2"
For %%A In (*.png *.doc) Do (
If Not Exist "%DirN%" MD "%DirN%"
If /I Not "%%~nxA"=="%~nx0" RoboCopy . "%DirN%" "%%A" /MOV 1>NUL
Set/A "limit-=1"
If !limit! Lss 0 GoTo Check_DirN
)
Echo(Task Done!
Timeout -1 1>Nul
Related
Trying to create a script that will take the third token of a file name, create a folder based on it and move the associated file to that folder.
Have got this so far:
#ECHO OFF
SETLOCAL
SET "sourcedir=D:\Sourcedir"
PUSHD %sourcedir%
FOR /f "tokens=1,2,3,4 delims=" %%a IN (
'dir /b /a-d "*.pdf"'
) DO (
ECHO MD %%c
ECHO MOVE "%%a %%b %%c %%d" .\%%c\
)
POPD
GOTO :EOF
Only problem is the folder being created is including the file extension where as I just need the folder to be named the third token.
Example file name:
"File Number 10.pdf
Expected folder name:
10
Thanks
Why did you use delims=? This will remove delimiter, and take whole line to %%a.
Try this:
#ECHO OFF
SETLOCAL
SET "sourcedir=D:\Sourcedir"
PUSHD %sourcedir%
FOR /f "tokens=1,2,3" %%a IN (
'dir /b /a-d "*.pdf"'
) DO (
ECHO MD %%~nc
ECHO MOVE "%%a %%b %%c" .\%%~nc\
)
POPD
GOTO :EOF
When no delims= set, it will use space. So %%c will be 10.pdf, ~n is to extract its name part.
This is based on your question, which you can concatenate %%a %%b %%c together with spaces, then it's simple.
If your filenames are more complicated, then an inner for loop is better.
-- Which another question already gave a great solution.
Here's an alternative, which will just use the last space delimited string/number, regardless of how many there are, (if there are none it will use the whole filename)!
#Echo Off
For %%A In ("D:\Sourcedir\*.pdf") Do Call :L "%%A"
Exit /B
:L
Set "F=%~n1"
Set "F=%F: ="&Set "F=%"
If Not Exist "%~dp1%F%\" MD "%~dp1%F%"
Move /Y %1 "%~dp1%F%"
And if you wanted to move only those which have at least one space, you can include that inside the For parentheses.
#Echo Off
For %%A In ("D:\Sourcedir\* *.pdf") Do Call :L "%%A"
Exit /B
:L
Set "F=%~n1"
Set "F=%F: ="&Set "F=%"
If Not Exist "%~dp1%F%\" MD "%~dp1%F%"
Move /Y %1 "%~dp1%F%"
You can run 2 for loops get the full name in the first, then split the name in the second loop, get the 3rd token, create the directory and then copy the actual file name from the first loop.
This way you do not need to try and patch the name together again, I know it works, but it is ugly and not prefered:
#echo off
setlocal enabledelayedexpansion
set "sourcedir=D:\Sourcedir"
pushd %sourcedir%
for %%a in (*.pdf) do (
set "var=%%a"
for /f "tokens=3" %%i in ("!var!") do (
echo md "%%~ni"
echo move "%%~a" "%%~ni"
)
)
popd
goto EOF
For more information on these commands, see help for each from cmd.exe i.e
for /?
set /?
setlocal /?
set and setlocal has very specific information regarding delayed expansion.
I have many folders in a directory which I need to rename with a fixed base name and a progressive number starting from 1 to infinite.
Path of folders have space and base folder is D:\Programmi Installati.
Example of folders to rename:
log_1
log_2
log_04-01-2019 15-15-11,51
log_01-01-2019 8-22-14,19
log_27-12-2018 14-23-18,28
log_aaaa
log_bbbb
log_5
log_6
log_02-01-2019 6-21-17,34
log_03-01-2019 21-18-16,22
Example of wanted folder names:
log_1
log_2
log_3
log_4
log_5
log_6
log_7
log_8
log_9
log_10
log_11
log_12
The numbers of folder to rename can be large, but the structure is the same.
I tryed more batch file but all fail when there are some folders with the wanted name (example log_5 or log_1)
The order is not important it is important that all the folders starting with "log" are renamed with an incrental number.
Code already tryed without success
:: 1 code
#echo off
setlocal enabledelayedexpansion
set counter=
for /d %%a in ("D:\Programmi Installati\log_*") do (
set /a counter+=1
ren "%%~fa" "log_!counter!"
)
pause
:: 2 code
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "Counter=1"
for /F "delims=" %%I in ('dir "D:\Programmi Installati\log*" /AD /B /ON 2^>nul') do ren "D:\Programmi Installati\%%I" "log_!Counter!" & set /A Counter+=1
endlocal
pause
:: 3 code
#ECHO OFF
#setlocal enabledelayedexpansion
Rem | Folder Path & CD To Location
Set "Folder=D:\Programmi Installati\"
CD %Folder%
Rem | Get Raw File Name
Set "Number=1"
for /F "tokens=*" %%A in ('dir "log*" /S /b /AD') do (
Rem | Rename Folder || Raw Name - %%~n1
rename "%%~nA" "log_!Number!"
Rem | Add One To Number
set /a "number+=1"
)
Goto :EOF
PAUSE
The codes over works only if there is no desired directory name in the directory otherwise do not rename folders.
This batch works differently, it
skips folders with the proper naming scheme (so they keep the number)
increments a counter and fills in possible gaps
:: Q:\Test\2019\01\11\SO_54149437.cmd
#Echo off
Pushd "D:\Programmi Installati\" || (Echo couldn't change dir&pause&goto :eof)
set Cnt=0
for /f "delims=" %%A in (
'dir /B /AD log_* ^| findstr /iV "^log_[0-9][0-9]*$" '
) Do Call :RenInc "%%A"
PopD
Goto :Eof
:RenInc
Set /A Cnt+=1
if Exist "log_%Cnt%" goto :RenInc
Ren "%~1" "log_%Cnt%"
The resulting names (there are only eleven, not twelve)
log_1
log_10
log_11
log_2
log_3
log_4
log_5
log_6
log_7
log_8
log_9
I am in the middle of batch extracting screenshots for contents we are planning to use on a tube site I am working on.
The jpeg files per content is labled as followed:
6c82c0239f6eb839-1
6c82c0239f6eb839-2
all the way to 120
The file name is different per content
a82384e2c46ba4af-1
a82384e2c46ba4af-2
etc.
They will all be extracted to a singe folder.
So I basically need a batch file that will create folders based on the content name without the dash and number and move all 120 jpegs in the folder with the content name.
For example:
Create folder named 6c82c0239f6eb839 and
move 6c82c0239f6eb839-1 to 6c82c0239f6eb839-120 in to the created folder.
I saw another thread with the following batch file. its pretty much what I want but the folder name is only 3 characters long and the files are copied to the newly created folders instead of moving them.
#echo off
SetLocal EnableDelayedExpansion
for /F "delims=" %%a in ('dir /b *.jpeg') do (
set Name=%%a
set Folder=!Name:~0,3!
xcopy /y "%%a" !Folder!\
)
Could someone change this so that it will display full file name without the dash and number for the folders and move files in its respective folders instead of copy?
Thank you
#echo off
setlocal
#rem Get each jpeg file.
for /F "delims=" %%A in ('2^>nul dir /b *.jpeg') do (
rem Get filename as token before the dash.
for /f "delims=-" %%B in ("%%~A") do (
rem Make dir if needed.
if not exist "%%~B" md "%%~B"
rem Check if isdir.
2>nul pushd "%%~B" && popd
if errorlevel 1 (
>&2 echo Failed isdir "%%~B".
) else (
rem Do the move operation.
>nul move /y "%%~A" "%%~B"
if errorlevel 1 (
>&2 echo Failed move "%%~A" to "%%~B"
)
)
)
)
exit /b %errorlevel%
The code is well remarked so if you want to understand
the evaluated code by changing #echo off to #echo on.
The use of %errorlevel% after the exit /b is not
required though will let you know what the errorlevel is
when #echo on is used.
The pushd tests for a directory
(even if it is a symlink).
errorlevel is checked to decide if to echo a
error message or do the move.
As the for loop variables are used direct, use of
enabledelayedexpansion is not needed.
Many commands support the argument of /? to get help
about the command. i.e. move /?.
If you only try to copy the correct jpeg to the correct folder, you can do this:
#echo off
SetLocal EnableDelayedExpansion
CD <CORRECT ROOT PATH>
for /F "delims=" %%a in ('dir /b *.jpeg') do (
set Name=%%a
REM I presume all the files have 16 characters before the dash
set Folder=!Name:~0,16!
IF NOT EXIST !Folder! MKDIR !FOLDER!
xcopy /y "%%a" !Folder!\
)
I was not able to test.
First of all, I would like to apologize for my manners regarding my initial post.
The answer by micheal_heath has resolved my issue.
Furthermore, I happened to find this post by user Salmon Trout from a different site which also worked.
Batch file to make folders with part of file name and then copy files
#echo off
setlocal enabledelayedexpansion
for %%A in (*.psd *.jpg) do (
echo file found %%A
for /f "delims=" %%B in ("%%A") do set fname=%%~nB
for /f "delims=" %%C in ("%%A") do set fextn=%%~xC
for /f "tokens=1* delims=_" %%D in ("!fname!") do set folname=%%D
echo folder name !folname!
if not exist "!folname!" (
echo Folder !folname! does not exist, creating
md "!folname!"
) else (
echo Folder !folname! exists
)
echo Moving file %%A to folder !folname!
move "%%A" "!folname!"
)
echo Finished
pause
I just changed the the following line remove the hypen and numbers to create folders for the file name properly.
for /f "tokens=1* delims=-***" %%D in ("!fname!") do set folname=%%D
I still lack the knowledge on why and how both methods work, but this has been an interesting start for me. I hope other beginners trying to solve a similar issue can find something useful from this post.
I have a directory that contains close to a million XML files. Needless to say, it takes forever to load (20+ minutes) So, I'm writing a script to divide the files into folders with the top level being year and having months under each year. There are 4 main filenames where the date can be extracted from the 3rd token and the rest from the second token. ie:
BA1253570001_BALMIS_20130617_TRC_0_109506738E.xml
BA1254260001_ACCTV21_20140430_AMR_0_1095611492.xml
BA1736330001_SWFTOUT_20140929_LIQ_1_MTBX553494.xml
BA1739240001_FEDOUT_20140904_LIQ_1_105633316M.xml
The rest are like this:
EODMESS_20140718_MTBX473286.xml
MSGCONF_20140410_109558667V.xml
I'm sure there is an easier way to do it, but here is my code so far:
#echo on
setlocal enabledelayedexpansion
Set "starttime=%time%"
pushd C:\temp\xmls
for /f %%a in ('dir /b/o:d *.xml') do (
call :ExtractDates %%a ret
echo %%a - !ret!
for /f "tokens=1" %%b in ("!ret!") do (
for /f "tokens=1-3 delims=/" %%c in ("%%b") do (
if not exist .\%%e md .\%%e
if not exist .\%%e\%%c md .\%%e\%%c
if %%b equ %%c/%%d/%%e (
echo moving %%~nxa to .\%%e\%%c
echo move %%~nxa .\%%e\%%c
pause
)
)
)
)
echo Start time: %starttime%
echo End time: %time%
popd
exit /b
:ExtractDates
#echo on
setlocal enabledelayedexpansion
Echo Starting ExtractDates
for %%a in (BALMIS ACCTV21 FEDOUT SWFTOUT) do (
if not errorlevel 1 (set t=3) else set t=2
Call :ExtractFunc %~1 %%a !t! ret
endlocal&set "%~2=!ret!"&exit /b 0
)
exit /b
:ExtractFunc
#echo on
setlocal
Echo Starting ExtractFunc
for /f "tokens=%3 delims=_" %%a in (
'echo %~1^|Findstr "%~2"'
) do (
if not errorlevel 1 (
endlocal&set "%~4=%%a"&exit /b 0
)
)
exit /b
The problem is that the variable token isn't returning the right number and I'm not sure why. Any suggestions appreciated.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
PUSHD "%sourcedir%"
FOR /f "tokens=1*delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*_*_*.xml" '
) DO SET "filename=%%a"&CALL :process
POPD
GOTO :EOF
:process
FOR /f "tokens=2,3,6delims=_" %%m IN ("%filename%") DO SET "date1=%%m"&SET "date2=%%n"&SET "whichdate=%%o"
IF DEFINED whichdate SET "date1=%date2%"
IF NOT DEFINED date2 GOTO :eof
ECHO(MD .\%date1:~0,4%\%date1:~4,2%
ECHO(MOVE "%filename%" .\%date1:~0,4%\%date1:~4,2%\
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
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)
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)
Simply extract the two possible datestrings and use the presence of the sixth token to signal which of the two positions to select for generation of the destination directory. Skip if there's no third token (fails to fit mask specified)
Then select the required field to date1 and do some substringing.
I've been working on a batch script (.bat) to change file name to the same folder name 3 levels up but no luck. I can only get it to rename 1 level up. There are multiple files in multiple folders.
Any help would be greatly appreciated.
I don't completely understand the intent of your current code. But the following will rename a given file based on the folder 3 levels up. Note that you can only rename one file with a given extension per folder using this strategy.
#echo off
setlocal
set "file=H:\Techs\Exported Videos\Scenario\1-CAS IED\Media player format\A8 West\abc.avi"
for %%A in ("%file%") do for %%B in ("%%~A\..\..\..") do ren "%%~A" "%%~nxB%%~xA"
Note that I include the extension of the folder name because folder names can include dots.
EDIT
Based on OP's comments, I believe the following will properly rename all relevant .avi files. The code has been tested, and works in my hands. Simply set the root and files values as appropriate.
#echo off
setlocal
set "root=H:\Techs\Exported Videos\Scenario"
set "files=*.avi"
for %%A in ("%root%\.") do set "root=%%~fA"
for /f "delims=" %%A in ('dir /b /s /a-d "%root%\%files%"') do (
for %%B in ("%%~A\..\..\..") do (
if /i "%%~dpB" equ "%root%\" ren "%%~A" "%%~nxB%%~xA"
)
)
you might try this:
#echo off &setlocal
set /a PathLevel=3
for %%a in (
"H:\Techs\Exported Videos\Scenario\1-CAS IED\Media player format\A8 West\1-CAS IED.avi"
"H:\Techs\Exported Videos\Scenario\2-SAF\Media player format\A8 PTZ\2-SAF.avi"
) do (
call:doit "%%~a"
)
goto:eof
:doit
set "fname=%~1"
set /a cnt=0
for %%a in ("%fname:\=","%") do set /a cnt+=1
set /a cnt-=PathLevel
for %%a in ("%fname:\=","%") do (
set /a cnt-=1
setlocal enabledelayedexpansion
if !cnt! equ 0 (
endlocal
set "nname=%%~a"
) else endlocal
)
echo ren "%fname%" "%nname%%~x1"
goto:eof
output is:
ren "H:\Techs\Exported Videos\Scenario\1-CAS IED\Media player format\A8 West\1-CAS IED.avi" "1-CAS IED.avi"
ren "H:\Techs\Exported Videos\Scenario\2-SAF\Media player format\A8 PTZ\2-SAF.avi" "2-SAF.avi"