3
\$\begingroup\$

This script sorts files from current directory into known subdirectories. it is built for speed because the keyword database used can be up to 20kb. each line of the database has subdirname,1,keywords?string where the number is how many points this keyword is worth. It then counts these points and puts the file to the subdir with the most points. minimum points for a move is 2. The last line in each database file is missing,0,not appearing in this directory.

dir *.* /a-d >nul 2>nul || exit /b
set "tempfile=%temp%\sortables"
set "sourcedir=%~1"
setlocal enabledelayedexpansion

:: set datafile, categories according to where we are
set "categories="
if /i "%cd%"=="d:\videos" (
    set "datafile=videos"
    set "categories=series porno"
)
if /i "%cd%"=="d:\videos\movies" (
    set "datafile=movies"
    set "categories=features psychedelic pornography concerts standup featurettes documentaries"
)
if /i "%cd%"=="d:\videos\movies\documentaries" (
    set "datafile=docu"
    set "categories=1-scarcity 2-globalists 3-disinformation 4-agendas 5-abundance"
)
if /i "%cd%"=="d:\videos\movies\features" (
    set "datafile=films"
    set "categories=comedy drama action thriller venture crime horror mystery fantasy science western warfare"
)
if /i "%cd%"=="d:\videos\series" (
    set "datafile=series"
    set "categories=comedy stories1 stories2 reality trippy"
)
if /i "%cd%"=="d:\videos\series\comedy" (
    set "datafile=comedy"
    set "categories=cartoon classic modern reality sketch standup"
)
if /i "%cd%"=="d:\videos\series\pilots" (
    set "datafile=pilots"
    set "categories=reality drama comedy scifi fantasy crime mystery action thriller"
)
if /i "%cd%"=="d:\videos\shorts" (
    set "datafile=shorts"
    set "categories=psychedelic entertaining music media useful conspiracies"
)
if /i "%cd%"=="d:\videos\shorts\media" (
    set "datafile=media"
    set "categories=trailers games fandom extras facts analysis features"
)
if /i "%cd%"=="d:\videos\shorts\music" (
    set "datafile=music"
    set "categories=bigbeat classical clubbing country electro swing reggae dub experimental geeky metal rap rock synthwave triphop xxx"
)
if not defined categories exit /b
set database=d:\system\scripts\%datafile%.txt
if not exist "%database%" echo critical error: database %datafile%.txt doesn't exist && exit /b
if defined v%~n0 echo sorting "%cd%"

:: =============================================================================================================================
::      setup sorting categories (do not change anything lightly or without backup after this point)
:: =============================================================================================================================

:: do not remove this echo off or this script will stop working
@echo off

set "sortingcategories="
for %%a in (%categories%) do set "sortingcategories=!sortingcategories!,%%~a"
set "sortingcategories=%sortingcategories: =_%"

:: =============================================================================================================================
::      create tempfile containing lines of: name|sortingcategory|weight
:: =============================================================================================================================
(
 for /f "tokens=1,2,*delims=," %%s in (%database%) do (
 set "sortingcategory=%%s"
 set "sortingcategory=!sortingcategory: =_!"
 for /f "delims=" %%a in (
  'dir /b /a-d "%sourcedir%\*%%u*" 2^>nul'
  ) do (
   echo %%a^|!sortingcategory!^|%%t^|%%s^|%%u
 )
)
)>"%tempfile%"
type "%tempfile%" >>d:\system\scripts\sorter.log

:: =============================================================================================================================
::      reset and call processing for each file in tempfile + dummy (helps counting the last score?)
:: =============================================================================================================================

set "lastname="
for /f "tokens=1,2,3,*delims=|" %%a in ('sort "%tempfile%"') do call :resolve %%b %%c "%%a"
call :resolve dummy 0
:: declare failures
if defined v%~n0 if not "%datafile%"=="videos" if not "%datafile%"=="music" if not "%datafile%"=="media" (
    dir "%~1\*" /a-d >nul 2>nul && for /f "delims=" %%q in ('dir %1 /b /a-d') do echo unsortable in %datafile% "%%q"
)
exit /b

:resolve
IF "%~3" equ "%lastname%" GOTO accum
:: report and reset accumulators
IF NOT DEFINED lastname GOTO RESET
SET "winner=none"
SET /a maxfound=1
FOR %%v IN (%sortingcategories%) DO (
 FOR /f "tokens=1,2delims=$=" %%w IN ('set $%%v') DO IF %%x gtr !maxfound! (SET "winner=%%v"&SET /a maxfound=%%x)
)
if "%winner%"=="none" goto reset
SET "winner=%winner:_= %"
SET "lastname=%lastname:&=and%"
:: this has a problem with different type of dash -
echo "%lastname%" | find /i ".tmp" >nul && exit /b
:: this once overwrote a same-name, much smaller file, wtf?
if "%winner%"=="porno" move "%sourcedir%\%lastname%" "d:\shame\" >nul && echo "d:\shame\%lastname%"
if not "%winner%"=="porno" move "%sourcedir%\%lastname%" "%sourcedir%\%winner%\" >nul && echo "%sourcedir%\%winner%\%lastname%"
if "%winner%"=="features" if exist "%sourcedir%\%lastname%" move "%sourcedir%\%lastname%" "%sourcedir%\%winner%\" >nul && echo "%sourcedir%\%winner%\%lastname%"
:: before or after successful filing we could do a surgical dupe check for only that file, rendering the old style obsolete

:RESET
FOR %%v IN (%sortingcategories%) DO SET /a $%%v=0
SET "lastname=%~3"
:accum
SET /a $%1+=%2

It runs nearly perfectly. However, for a file in d:\videos to find its way to, say, d:\videos\shorts\music\electro, this script will be run three times, once for every subdir. Should this be reworked so it can figure out the final resting place in one go? Would that be feasible? Would it require a single large database file, making it slow again?

I know it's crazy this is done in batch but it's the only language I know. I would love to know about the better ways of doing this.

\$\endgroup\$
1
\$\begingroup\$

Maybe the following wrapper script could help:

@ECHO OFF
SETLOCAL EnableExtensions
set "_OrigScript=D:\bat\CodeReview\202927.bat"    # change to match your terms
CD /D "d:\videos"
FOR /D /r %%G in (.) DO (
  pushd %%~fG
  call "%_OrigScript%"
  popd
)

Explanation (required reading):

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.