2017-07-19 2 views
1

私は、ファイル内の既知のキーワードを調べることによって、ビデオファイルをフォルダに分類するスクリプトを作成しています。キーワードの量が制御不能になるにつれて、スクリプトは非常に遅くなり、各ファイルが処理されるまで数秒かかる。キーワードに基づいてファイルをソートするには、さらにデータベースとソリューションが必要です

@echo off  
cd /d d:\videos\shorts 
if /i not "%cd%"=="d:\videos\shorts" echo invalid shorts dir. && exit /b 

:: auto detect folder name via anchor file 
for /r %%i in (*spirit*science*chakras*) do set conspiracies=%%~dpi 
if not exist "%conspiracies%" echo conscpiracies dir missing. && pause && exit /b 
for /r %%i in (*modeselektor*evil*) do set musicvideos=%%~dpi 
if not exist "%musicvideos%" echo musicvideos dir missing. && pause && exit /b 

for %%s in (*) do set "file=%%~nxs" & set "full=%%s" & call :count 
for %%v in (*) do echo can't sort "%%~nv" 
exit /b 

:count 
set oldfile="%file%" 
set newfile=%oldfile:&=and% 
if not %oldfile%==%newfile% ren "%full%" %newfile% 

set count=0 
set words= & rem 
echo "%~n1" | findstr /i /c:"music" >nul && set words=%words%, music&& set /a count+=1 
echo "%~n1" | findstr /i /c:"official video" >nul && set words=%words%, official video&& set /a count+=2 
set words=%words:has, =has % 
set words=%words: , =% 
if not %count%==0 echo "%file%" has "%words%" %count%p for music videos 
set musicvideoscount=%count% 

set count=0 
set words= & rem 
echo "%~n1" | findstr /i /c:"misinform" >nul && set words=%words%, misinform&& set /a count+=1 
echo "%~n1" | findstr /i /c:"antikythera" >nul && set words=%words%, antikythera&& set /a count+=2 
set words=%words:has, =has % 
set words=%words: , =% 
if not %count%==0 echo "%file%" has "%words%" %count%p for conspiracies 
set conspiraciescount=%count% 

set wanted=3 
set winner=none 

:loop 
:: count points and set winner (in case of tie lowest in this list wins, sort accordingly) 
if %conspiraciescount%==%wanted% set winner=%conspiracies% 
if %musicvideoscount%==%wanted% set winner=%musicvideos% 
set /a wanted+=1 
if not %wanted%==15 goto loop 

if not "%winner%"=="none" move "%full%" "%winner%" >nul && echo "%winner%%file%" && echo. 

各キーワードの「重み値」に注目してください。各カテゴリの合計ポイント数をカウントし、最大値を見つけてそのカテゴリに指定されたフォルダにファイルを移動します。また、見つかった単語も表示され、最後にはソートできないファイルがリストされるので、キーワードを追加したり、重み値を微調整したりすることができます。

このサンプルのフォルダとキーワードの数を最小限に抑えました。完全なスクリプトは、6つのフォルダとすべてのキーワード(および成長)と64kのサイズを持っています。

+0

PowerShellで必要な場合は、まず基本コードを自分で実行し、問題があれば*ここに戻り、何が動作していないのか特定の質問をしてください。私が見ることができるところから、既存のバッチコードの主な問題はパフォーマンスです。そうですか? – gravity

+0

私は理解します。そうですね、パフォーマンスです。私はこれが間違ったやり方の主な例だと思う。私が抱えている唯一の実際の問題は特殊文字です。 – bricktop

答えて

3
@ECHO OFF 
SETLOCAL 
SET "sourcedir=U:\sourcedir" 
SET "tempfile=%temp%\somename" 
SET "categories=music conspiracies" 
REM SET "categories=conspiracies music" 
(
FOR /f "tokens=1,2,*delims=," %%s IN (q45196316.txt) DO (
FOR /f "delims=" %%a IN (
    'dir /b /a-d "%sourcedir%\*%%u*" 2^>nul' 
) DO (
    ECHO %%a^|%%s^|%%t 
) 
) 
)>"%tempfile%" 

SET "lastname=" 

FOR /f "tokens=1,2,*delims=|" %%a IN ('sort "%tempfile%"') DO (
CALL :resolve %%b %%c "%%a" 
) 
:: and the last entry... 
CALL :resolve dummy 0 

GOTO :EOF 

:resolve 
IF "%~3" equ "%lastname%" GOTO accum 
:: report and reset accumulators 
IF NOT DEFINED lastname GOTO RESET 
SET "winner=" 
SET /a maxfound=0 
FOR %%v IN (%categories%) DO (
FOR /f "tokens=1,2delims=$=" %%w IN ('set $%%v') DO CALL :compare %%w %%x 
) 
IF DEFINED winner ECHO %winner% %lastname:&=and% 
:RESET 
FOR %%v IN (%categories%) DO SET /a $%%v=0 
SET "lastname=%~3" 
:accum 
SET /a $%1+=%2 

GOTO :eof 

:compare 
IF %2 lss %maxfound% GOTO :EOF 
IF %2 gtr %maxfound% GOTO setwinner 
:: equal scores use categories to determine 
IF DEFINED winner GOTO :eof 
:Setwinner 
SET "winner=%1" 
SET maxfound=%2 
GOTO :eof 

sourcedirの設定を状況に合わせて変更する必要があります。

このカテゴリのデータを含むファイルを使用してテストしました。

music,6,music 
music,8,Official video 
conspiracies,3,misinform 
conspiracies,6,antikythera 
missing,0,not appearing in this directory 

あなたの問題は、findstrを繰り返し実行することは時間がかかることです。

このアプローチでは、category,weight,maskの行を含むデータファイルを使用します。 categories変数(スコアが同じである場合の)優先順にカテゴリのリストを含む

%%u%%tマスクに、%%sにカテゴリを割り当て、重みをデータ・ファイルを読み込み、次に使用してディレクトリスキャンを行いますマスク。これにより、echoの各テンポラリファイルには、それぞれの名前が一致する形式のname|category|weightという形式で表示されます。 dirは、最初のスキャンの後に非常に高速に見えます。

結果の一時ファイルには、各ファイル名+カテゴリと重みの合計が1行になるため、ファイル名が複数のカテゴリに適合する場合、複数のエントリが作成されます。

次に、ファイルのソート済みバージョンをスキャンし、スコアを解決します。

最初に、ファイル名が変更された場合は、最後のファイル名について報告することができます。これは、変数$categorynameの値を比較することによって行われます。これらは、%categories%の順番でスキャンされるので、スコアの等価性がある場合、リストの最初のカテゴリが選択されます。スコアはリセットされ、lastnameは新しいファイル名に初期化されます。

私たちはそのように$categoryname

にスコアを蓄積する - 私はそれが少し速くなりますと信じています。


私はいくつかの重要なコメントを追加しましたリビジョン

@ECHO OFF 
SETLOCAL ENABLEDELAYEDEXPANSION 
SET "sourcedir=U:\sourcedir" 
SET "tempfile=%temp%\somename" 
SET "categories="rock music" music conspiracies" 
REM SET "categories=conspiracies music" 
:: set up sorting categories 
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 (q45196316.txt) 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%" 

SET "lastname=" 

SORT "%tempfile%">"%tempfile%.s" 

FOR /f "usebackqtokens=1,2,3delims=|" %%a IN ("%tempfile%.s") DO (

CALL :resolve %%b %%c "%%a" 
) 
:: and the last entry... 
CALL :resolve dummy 0 

GOTO :EOF 
:: resolve by totalling weights (%2) in sortingcategories (%1) 
:: for each name (%3) 
:resolve 
IF "%~3" equ "%lastname%" GOTO accum 
:: report and reset accumulators 
IF NOT DEFINED lastname GOTO RESET 
SET "winner=none" 
SET /a maxfound=0 
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) 
) 
ECHO %winner:_= % %lastname:&=and% 
:RESET 
FOR %%v IN (%sortingcategories%) DO SET /a $%%v=0 
SET "lastname=%~3" 
:accum 
SET /a $%1+=%2 

GOTO :eof 

カテゴリ名にスペースを含めることができます。set catagories...ステートメント内で名前を引用する必要があります(レポートの目的で)。

sortingcategoriesが自動的に導出されます。これはソートにのみ使用され、単に名前のスペースがアンダースコアで置き換えられたカテゴリです。

tempfileの作成では、カテゴリはアンダースコア(sortingcategory)を含むように処理され、最終的な配置が解決されると、アンダースコアが削除されてカテゴリ名が返されます。

負の重みを適切に処理する必要があります。

+0

私は甘い時間をかけてコードを理解しています。それはうまくいきますが、私はそれにスペースでカテゴリ名を持つ可能性を持っていたと思います。音楽の代わりに「ミュージックビデオ」を使ってみましたが、うまくいきませんでした。私はこの時点で多くの編集を行うのに十分なコードを理解していません... – bricktop

+0

私は気づいたのですが、データベースファイル内でワイルドカードとして '? 'を使うことができます。非常に素晴らしい!私は負の重み値を使うこともできればいいと思いますが、難しいものを並べ替えると助かります。現在、負の値を使用すると、ファイルが最初のカテゴリに格納されます。 – bricktop

+0

ああ私は、ほぼ完全な書き換えのように見えます。私はあなたに深刻な感謝の義務を負っているので、ありがとう!それは私があなたの最後のことを悩ます可能性があると言われています。どのようなキーワードが見つかったのかエコーを追加できますか?私は自分でそれをすることすらできないと確信しています。私はこれを解読しようとするとちょっと混乱していることを認めなければならない。 – bricktop

関連する問題