I have a folder with 110.000 files and I want a way to break this folder into multiple subfolders containing say 3000 files each (with a batch script perhaps?). (Trying a copy/paste with WinExplorer gets stuck in "Preparing to Copy".)
For example:
BigFolder
|
NewFolder
| | | | |
Sub1 Sub2 Sub3 Sub4 Sub5...
I am surprised to find the same case of mine.
I had 30,000 files that needed to be sorted, so I asked question on this page:
Fast methods to copy(move) files in batch file
This is Compo's script:
#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=700"
For %%A In (*.bat *.cmd *.txt) 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
And this is what I use and I edited for a bit for the purpose:
#Echo Off
If /I Not "%__CD__%"=="%~dp0" PushD "%~dp0" 2>Nul||Exit/B
taskkill /f /im explorer.exe >nul
taskkill /f /im SearchIndexer.exe >nul
sc stop WSearch >nul
sc config WSearch start= disabled >nul
SetLocal EnableDelayedExpansion
Set "DirN=-1"
:Check_DirN
Set/A "DirN+=1"
If Exist "%DirN%" GoTo Check_DirN
cls
echo Moving files to Directory %DirN%...
Set "limit=2999"
MD "%DirN%"
For %%A In (*.html) Do (
RoboCopy . "%DirN%" "%%A" /MOV 1>NUL
Set/A "limit-=1"
If !limit! Lss 0 GoTo Check_DirN
)
Echo(Task Done!
start explorer.exe
start SearchIndexer.exe
sc config WSearch start= delayed-auto >nul
sc start WSearch >nul
Timeout -1 1>Nul
You can remove taskkill, start and sc part if desired.
I added this part because explorer and Windows Search Indexer will cause waste of memory when moving files. I recommend you to run the script with Administrator privilege.
Try to test the script in small scale to see if it does work.
Related
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
I want to make a script which finds as quickly as possible first folder named Target starting from root location D:\ and return its absolute path.
Folder structure of root location (D:\) can be like this:
-DontSearchHereFolder
-Folder1\Subfolder1\SSubfolder1\SSSubfolder1\
-Folder2\Subfolder2\SSubfolder2\TargetFolder
-DontSearchHereFolder2
-Folder3\Subfolder3\
Output of the script should be: D:\Folder2\Subfolder2\SSubfolder2\TargetFolder
For now I tried 2 methods but it's not quick enough:
(1)
set TG=\TargetFolder
set root=D:\
cd %root%
for /f "delims=" %%a in ('dir /b /s /a:d "%root%" ^|findstr /e /i "%TG%"') do set "folderpath=%%~a"
(2)
for /d /r "%root%" %%a in (*) do if /i "%%~nxa"=="%TG%" set "folderpath=%%a"
(1) is quicker than (2)
Question1: Is it possible to specify in command to search only for a maximum of 2 folders "down" from root (e.g. D:\Folder1\Subfolder1) ?
Question2: Is it possible to specify folders that should be automatically skipped (e.g. DontSearchHereFolder1&2)
This batch code is exactly for what you have asked for optimized for speed. It ignores the two specified directories on first level and it searches for the folders maximal two folder levels deep.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "Root=D:"
set "TG=TargetFolder"
set "Ignore1=DontSearchHereFolder"
set "Ignore2=DontSearchHereFolder2"
for /D %%A in ("%Root%\*") do (
if "%%~nxA" == "%TG%" set "FolderPath=%%A" & goto Found
if not "%%~nxA" == "%Ignore1%" (
if not "%%~nxA" == "%Ignore2%" (
for /D %%B in ("%%A\*") do (
if "%%~nxB" == "%TG%" set "FolderPath=%%B" & goto Found
for /D %%C in ("%%B\*") do if "%%~nxC" == "%TG%" set "FolderPath=%%C" & goto Found
)
)
)
)
echo Could not find folder: "%TG%"
goto EndSearch
:Found
echo Found folder: "%FolderPath%"
:EndSearch
endlocal
The string comparisons are done case-sensitive for maximum speed.
No recursive subroutine calls are used as usually would be done for such tasks for maximum speed.
The comparisons for the directories to ignore in root folder are coded in batch script directly not using an array or a list of folder names for maximum speed.
Delayed expansion is not used for faster processing the command lines.
But much faster would be coding an executable in C/C++/C# for that task as processing the command lines of the batch file takes most likely the most time on searching for the folder.
Note: Command FOR ignores folders with hidden attribute set.
Well, I use for such tasks shareware tool Total Commander which supports searching only in selected folders for a specific folder not more than X levels deep extremely fast.
This should take into account all the limits indicated in the question, but unless a lot of folders are found inside the indicated exclusions, I don't think this should be faster, just give it a try
#echo off
setlocal enableextensions disabledelayedexpansion
set "source=d:\"
set "target=TargetFolder"
set "maxLevels=2"
set excludeFolders= "DontSearchHereFolder" "DontSearchHereFolder2"
for %%s in ("%source%") do for /f "tokens=*" %%f in ('
robocopy "%%~fs." "%%~fs." /l /nfl /njh /njs /nc /ns /s
/xd %excludeFolders% /lev:%maxLevels%
^| findstr /e /i /l /c:"\\%target%\\"
^| cmd /v /q /c"set /p .= &&(echo(!.!)"
') do echo "%%~f"
I think this is the fastest possible way to do this:
#echo off
setlocal EnableDelayedExpansion
if "%1" neq "" goto %1
set "root=D:\"
set "TG=TargetFolder"
set "exclude=/DontSearchHereFolder1/DontSearchHereFolder2/"
"%~F0" Input | "%~F0" Output > result.txt
set /P "folderpath=" < result.txt
del result.txt
echo First folder: %folderpath%
goto :EOF
:Input
cd "%root%"
for /D %%a in (*) do if "!exclude:/%%a/=!" equ "%exclude%" (
cd "%%a"
dir /B /S /A:D "%TG%" 2>NUL
cd ..
)
exit /B
:Output
set /P "folder="
echo "%folder%"
set "i=0"
for /F "tokens=2" %%a in ('tasklist /FI "IMAGENAME eq cmd.exe" /FO TABLE /NH') do (
set /A i+=1
if !i! equ 2 taskkill /PID %%a /F
)
exit /B
The folders to exclude are given in a slash-separated list; if this list is longer, the process run faster because more folders are skipped. The target folder is search in each one of the non-excluded folders via a dir /B /S /AD "%TG%" command, that is faster than any combination of other commands. The process ends as soon as the first folder name is received in the rigt side of the pipe; the remaining processing at left side of the pipe is cancelled via a taskkill command.
I'm in the process of making a script that selects 25 random tracks from a user specified folder and adds them into an .m3u playlist. The trouble I have is that my music folders include various other files as well (eg: .txt, .jpg, .png, .nfo, etc...)
So I'm looking for a way of excluding the extensions listed above, limiting the script to just work with audio files. Any help would be much appreciated!
Here is the code so far... It has been stitched together from various sources so accept my apologies if it is a little crude:
#echo off
title Multiple Choice Menu
:home
cls
echo.
echo Select a genre:
echo =============
echo.
echo 1) Jungle
echo 2) D'n'B
echo 3) Reggae
echo 4) Hip-Hop
echo 5) Exit
echo.
set /p genre=Type option:
if "%genre%"=="1" cd /D "D:\NL Safe 2.0\High Quality\Jungle"
if "%genre%"=="2" cd /D "D:\NL Safe 2.0\High Quality\DnB\Standard DnB"
if "%genre%"=="3" cd /D "D:\NL Safe 2.0\High Quality\Reggae
if "%genre%"=="4" cd /D "D:\NL Safe 2.0\High Quality\Hip-Hop"
if "%genre%"=="5" exit
:: Clear existing Playlist
#echo. > C:\Users\Brew\Desktop\random.m3u
:: Create numbered list of files in a temporary file
set "tempFile=%temp%\%~nx0_fileList_%time::=.%.txt"
dir /b /s /a-d %1 | findstr /n "^" >"%tempFile%"
:: Count the files
for /f %%N in ('type "%tempFile%" ^| find /c /v ""') do set cnt=%%N
:: Open 25 random files
for /l %%N in (1 1 25) do call :openRandomFile
:: Delete the temp file
del "%tempFile%"
:openRandomFile
set /a "randomNum=(%random% %% cnt) + 1"
for /f "tokens=1* delims=:" %%A in (
'findstr "^%randomNum%:" "%tempFile%"'
) do (
setlocal EnableDelayedExpansion
set tune=%%B
#echo !tune! >> C:\Users\Brew\Desktop\random.m3u
)
Assuming your song's folder is on %1.
The dir command supports wildcards in the idea that
dir *.txt *.xml
will only list .txt and .xml files.
So you can try doing this instead:
...
:: Create numbered list of files in a temporary file
set "tempFile=%temp%\%~nx0_fileList_%time::=.%.txt"
pushd %1
dir /b /s /a-d *.mp3 *.EXT1 *.EXT2 | findstr /n "^" >"%tempFile%"
popd
...
Where EXT will be the extensions you want to match.
This will create your %tempFile% with only the files you want. Since the code that selects a file ramdomly works, as I see, over this file, it won't need to change at all.
I couldn't get dir to work with both target directory and wildcards.
Hope it helps.
This is why i used pushd and popd.
Thanks Daniel,
I had another go at it an finally got something working on my own. I used a series of If statements to put the random file through an extension validation check
This is the working script
#echo off
title Multiple Choice Menu
:home
cls
echo.
echo Select a task:
echo =============
echo.
echo 1) Jungle
echo 2) D'n'B
echo 3) Reggae
echo 4) Hip-Hop
echo 5) Exit
echo.
set /p genre=Type option:
if "%genre%"=="1" cd /D "D:\NL Safe 2.0\High Quality\Jungle"
if "%genre%"=="2" cd /D "D:\NL Safe 2.0\High Quality\DnB\Standard DnB"
if "%genre%"=="3" cd /D "D:\NL Safe 2.0\High Quality\Reggae
if "%genre%"=="4" cd /D "D:\NL Safe 2.0\High Quality\Hip-Hop"
if "%genre%"=="5" exit
:: Clear existing Playlist
#echo. > C:\Users\Brew\Desktop\random.m3u
:: Create numbered list of files in a temporary file
set "tempFile=%temp%\%~nx0_fileList_%time::=.%.txt"
dir /b /s /a-d %1 | findstr /n "^" >"%tempFile%"
:: Count the files
for /f %%N in ('type "%tempFile%" ^| find /c /v ""') do set cnt=%%N
:openRandomFile
echo opening random file.....
set /a "randomNum=(%random% %% cnt) + 1"
for /f "tokens=1* delims=:" %%A in (
'findstr "^%randomNum%:" "%tempFile%"'
) do (
setlocal EnableDelayedExpansion
set tune=%%B
FOR %%i IN ("!tune!") do call :CheckifMusic
)
:CheckifMusic
echo checking now
FOR %%i IN ("!tune!") DO (
SET fileextension=%%~xi
IF !fileextension!==.aif goto ResultTrue
IF !fileextension!==.flac goto ResultTrue
IF !fileextension!==.m4a goto ResultTrue
IF !fileextension!==.mp3 goto ResultTrue
IF !fileextension!==.wav goto ResultTrue
IF !fileextension!==.wma goto ResultTrue
echo fail
echo !fileextension!
goto openRandomFile
:ResultTrue
echo pass
echo !fileextension!
#echo !tune! >> C:\Users\Brew\Desktop\random.m3u
set /A COUNTER=COUNTER+1
IF !COUNTER!==25 (
echo finished
pause
goto Done
) ELSE (
goto openRandomFile
)
:Done
echo.
:: Delete the temp file
del "%tempFile%"
exit
)
pause
Probably not the cleanest way to do it, but hey - It works!
replace
dir /b /s /a-d %1 | findstr /n "^" >"%tempFile%"
with
dir /b /s /a-d %1 | findstr /n /L /E /I /c:".mp3" /c:".wav">"%tempFile%"
Where the /c:".mp3"... can be extended as many times as you desire to select your target filetypes.
or
with
dir /b /s /a-d %1 | findstr /n /V /L /E /I /c:".jpg" /c:".txt">"%tempFile%"
Again repeating the /c:".jpg"... as many times as you desire to select your target exclude-me filetypes.
The /i means "case-insensitive", /e means "at the end of the line" /L means "literal match, not regex" and /v means "output non-matching"
i want to make an auto backup script for my office. i've do some research and finally get some light bulb, but the problem is that my code just work in Windows 7 and won't work in Windows XP. so how do i solve this? Here is my code
echo off
setlocal enabledelayedexpansion
:FIND.BACKUP.DRIVE.LETTER
set start.dir=%systemdrive%
J:
%cls%
if not "%cd:~0,2%"=="%start.dir%" goto next
I:
%cls%
if not "%cd:~0,2%"=="%start.dir%" goto next
H:
%cls%
if not "%cd:~0,2%"=="%start.dir%" goto next
G:
%cls%
if not "%cd:~0,2%"=="%start.dir%" goto next
if "%cd:~0,2%"=="%start.dir%" (
echo WAITING FOR FLASH MEDIUM TO BE CONNECTED . . .
if exist "%windir%\system32\timeout.exe" timeout /t 1 /nobreak >nul
if not exist "%windir%\system32\timeout.exe" pause
goto FIND.FLASH.DRIVE.LETTER
)
:next
set start.hour=%time:~0,2%
set start.min=%time:~3,2%
REM FLASH.DRIVE IS THE FLASH DRIVE.
set flash.drive=%cd:~0,2%
set date="%date:~7,2%-%date:~4,2%-%date:~10,4%"
mkdir "%userprofile%\desktop\a\%date%"
xcopy "%flash.drive%\*.*" /s /c /d /e /h /i /r /y %userprofile%\desktop\a\%date%
if not exist %flash.drive% set /a total.time=((((%time:~0,2%-%start.hour%)... && echo Flash Drive has been in for !total.time! minutes. && Pause>nul
#pause
thanks
This should be reliable, to do the same task.
Are you sure that you need the /d switch in xcopy?
#echo off
:loop
echo waiting... Please insert the flash drive...
ping -n 3 "" >nul
set "drv="
for %%a in (g h i j) do if exist "%%a:\" set "drv=%%a:"
if not defined drv goto :loop
REM drv IS THE FLASH DRIVE.
set start.hour=%time:~0,2%
set start.min=%time:~3,2%
set "d8=%date:~7,2%-%date:~4,2%-%date:~10,4%"
xcopy "%drv%\*.*" /s /c /d /e /h /r /y "%userprofile%\desktop\a\%d8%\"
set end.hour=%time:~0,2%
set end.min=%time:~3,2%
pause
I believe your calculation of total time is broken, and is something that you can work on.
I want to solve one question about path.
I have this code take in this forum who separetes stereo files in 2 mono files:
#ECHO OFF
SETLOCAL
for %%n in (*.wav) do CALL :runsox "%%n"
GOTO :eof
:runsox
CALL :wait
START "%~1.left" C:\sox\sox.exe %~1 -c 1 %~1.left.flac remix 1
CALL :wait
START "%~1.right" C:\sox\sox.exe %~1 -c 2 %~1.right.flac remix 2
GOTO :eof
:wait
FOR /f %%c IN ('tasklist^|find /i /c "sox.exe"') DO SET running=%%c
IF %running% GEQ 6 timeout /t 5 >nul&GOTO wait
GOTO :eof
but I want know how is possible make a little mod to move lefts file on a subfolder eg. /left and right files in /right in the main code without needed execute other batch:
I did that in a separete batch:
move *.wav.left.wav left/
move *.wav.left.wav right/
#echo off
setlocal enableextensions disabledelayedexpansion
2>nul (
md right
md left
)
for %%a in (*.wav) do (
call :wait
start "%%~na.left" C:\sox\sox.exe "%%~fa" -c 1 "%%~dpa\left\%%~na.left.flac" remix 1
call :wait
start "%%~na.right" C:\sox\sox.exe "%%~fa" -c 2 "%%~dpa\right\%%~na.right.flac" remix 2
)
goto :eof
:wait
FOR /f "skip=4 tokens=5 delims=," %%p IN ('
tasklist /fo:csv /nh /fi "imagename eq sox.exe"
') do ( >nul timeout /t 5 & goto :wait )
GOTO :eof
The for replaceable parameter %%a will hold the reference to the file being processed, so we can use this reference to obtain partial information (see for /? for the full list)
%%~na is the name of the file without extension
%%~fa is the full path to the file
%%~dpa is the drive and path where the file is stored
Using the indicated elements, command is changed to include the output folder.