Bricktop
Bricktop

Reputation: 153

sorter using scored keywords is acting up, and cannot echo without failing

this script sorts files into known subdirectories fast, by using database files filled with scored keywords. it works for the most part but sometimes it gives me errors that I can't figure out because it acts differently when the echo is turned on, and fails. this code is very important to me so this is a huge problem for me. the echo issue has to be fixed or it's unmanageable, no other possible problems need be addressed in this question! please help, it's largely beyond my understanding.

:: sorts files from %cd% into known subdirs according to database of scored keywords. minimum score is 2.0

rem todo if echo is on it fails with certain keywords like a simple *1x0* which is super weird
rem sometimes outputs unlocated error missing operator while still doing its job correctly
rem sometimes outputs unlocated error the system cannot fing the path specified
rem keywords or subdir names cannot contain spaces
rem fails with filenames with irregular dash characters
rem Adds * to start and end of keyword. start/end wildcards should be used surgically in the keywords file instead

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

rem set datafile, categories according to current location
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 stories 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 verbal echo sorting "%cd%"

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

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

rem =============================================================================================================================
rem     create tempfile containing lines of: name|sortingcategory|weight
rem =============================================================================================================================
(
 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

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

set "lastname="
echo off
for /f "tokens=1,2,3,*delims=|" %%a in ('sort "%tempfile%"') do call :resolve %%b %%c "%%a"
call :resolve dummy 0
rem declare failures
if defined verbal 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
rem 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%"
rem this has a problem with different type of dash -
rem this once overwrote a same-name, much smaller file, wtf?
if "%winner%"=="porno" move "%sourcedir%\%lastname%" "d:\nvidia\" >nul && echo "d:\nvidia\%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%"
rem 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

with echo turned on the error looks like this (note that this works fine when echo is off)

d:\VIDEOS>for /F "tokens=1,2,3,*delims=|" %a in ('sort "E:\TEMP\sortables"') do call :resolve %b %c "%a"

d:\VIDEOS>call :resolve !sortingcategory! 2 " for /F "delims=" %a in ('dir /b /a-d "\*1x0*" 2>nul') do (echo %a"
The syntax of the command is incorrect.

d:\VIDEOS>IF " for /F "delims" equ "" GOTO accum

d:\VIDEOS>

and this is the database file used (sorry for the lingo)

series,2,1x0
series,2,1x1
series,2,2x0
series,1,s0
series,1,s1
series,1,s2
series,1,s3
series,1,s4
series,1,s5
series,1,s6
series,1,s7
series,1,s8
series,1,s9
series,-1,s00
series,-1,e00
series,1,e0
series,1,e1
series,1,e2
series,1,e3
series,1,e4
series,1,e5
series,1,e6
series,1,e7
series,1,e8
series,1,e9
series,-1,extras
series,1,judge?judy?s
series,1,pilot
porno,1,amateur
porno,1,wet
porno,1,wmv
porno,1,xxx
missing,0,not appearing in this directory

it takes files from d:\videos and sorts them into d:\videos\series or d:\nvidia (hidden alternative to the other subdir d:\videos\porno)

Upvotes: 2

Views: 162

Answers (1)

michael_heath
michael_heath

Reputation: 5372

rem =============================================================================================================================
rem     create tempfile containing lines of: name|sortingcategory|weight
rem =============================================================================================================================
(
 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%"

change to

rem =============================================================================================================================
rem     create tempfile containing lines of: name|sortingcategory|weight
rem =============================================================================================================================
(
 for /f "usebackq 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 (
   >&3 echo %%a^|!sortingcategory!^|%%t^|%%s^|%%u
  )
 )
) 3>"%tempfile%"

Prior, echo off setting allows the echoed text to be redirected to file from stream 1.

When you set echo on, stream 1 includes the commands being echoed as well as the echoed text.

To avoid this merged output of commands and text, use an auxiliary stream. CMD supports auxiliary streams 3 through to 9.

The changed code sets the echoed text to redirect to the handle of stream 3 (>&3). The redirection to the file uses stream 3 (3>).

The errors posted is a delayed effect caused by echoed commands and text written to %tempfile% when using echo on with your posted code.

Added for loop option usebackq so the %database% path can be double quoted.

Upvotes: 2

Related Questions