@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q56380365.txt"
SET /a maxwords=0
rem for each line in the names file...to %%a
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO (
rem analyse line
CALL :words %%a
IF !wordcount! lss 0 GOTO :EOF
IF !wordcount! gtr !maxwords! SET /a maxwords=!wordcount!
)
:: Now have max # words in maxwords
:scandir
rem for each line in the names file...to %%a
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO (
REM how many words IN this line?
CALL :words %%a
IF !wordcount! equ %maxwords% (
rem read entire source directory using first word found as a filter
FOR /f "delims=" %%h IN ('dir /b /a-d "%sourcedir%\!#1!*" 2^>nul') DO (
CALL :matchname "%%h"
)
)
)
SET /a maxwords-=1
IF %maxwords% gtr 0 GOTO scandir
GOTO :EOF
:: Establish "Wordcount" and words as #*; subdir
:words
CALL :clear#
SET /a wordcount=0
SET "allwords=%~1 %~2"
SET "subdir=%~1"
SET "subdir2=%~2"
:: error if more than 2 "words" provided
IF "%~3" neq "" ECHO error IN line %*&SET /a wordcount=-1&GOTO :EOF
:wordloop
SET /a wordcount+=1
CALL :atom %allwords%
SET "#%wordcount%=%car%"
IF DEFINED cdr SET "allwords=%cdr%"&GOTO wordloop
GOTO :EOF
:: First word to car, remainder to cdr
:atom
SET "car=%1"
SET "cdr="
:atomlp
SHIFT
IF "%1" neq "" SET "cdr=%cdr% %1"&GOTO atomlp
IF DEFINED cdr SET "cdr=%cdr:~1%"
GOTO :EOF
:: remove variables starting #
:clear#
For %%b IN (#) DO FOR /F "delims==" %%a In ('set %%b 2^>Nul') DO SET "%%a="
GOTO :EOF
:: match filename in %1 to %maxwords% words in #* and move if matched
:matchname
SET "file=%~1"
SET /a match=1
:: replace commas, underscores [etc] with spaces
SET "file=%file:,= %"
SET "file=%file:_= %"
:matchloop
CALL :atom %file%
IF /i "%car%" neq "!#%match%!" GOTO :EOF
SET "file=%cdr%"
IF %match% neq %maxwords% SET /a match +=1&GOTO matchloop
:: all matched - move
MD "%destdir%\%subdir%, %subdir2%" 2>NUL >nul
ECHO MOVE "%sourcedir%\%~1" "%destdir%\%subdir%, %subdir2%"
GOTO :eof
Приземлился немного сложнее, чем я ожидал.Поскольку при этом используется delayedexpansion
, обычные предупреждения о специальных символах, таких как !
и &
и других не алфавитно-цифровых символах, должны быть тщательно обработаны.Обычные буквенно-цифровые и запятые должны быть в порядке.
Этот подход сначала проверяет файл имен - q56380365.txt
в моей системе.Вместо двух имен он также допускает строку в кавычках, поэтому можно использовать строку типа "van der Waals" Johannes
.Каждая строка передается в подпрограмму :words
, которая устанавливает subdir
и subdir2
для конструкции подкаталога, а также подсчитывает отдельные слова и помещает их в переменные окружения #1
, #2
.. #n
.Если более * 2 строк передаются в :words
, он возвращает wordcount
как -1, чтобы пометить ошибку, сообщив о содержании строки.Это обеспечивает правильное распознавание двух частей имени.
:words
само вызывает :atom
, что возвращает car
в качестве первой строки в списке и cdr
в качестве оставшихся строк.Причину, по которой они названы так, я оставлю кому-то другому в ekthplain.
Установив максимальное количество слов в файле имен, мы затем сканируем файл имен в обратном порядке числаслова - просто путем повторного чтения файла имен и сопоставления с уменьшающимся числом.Там, где у нас есть совпадение, мы сопоставляем имена файлов, используя первое слово в качестве фильтра.:matchname
принимает имя файла как %1
и заменяет любые запятые или подчеркивания пробелами для переменной file
.Затем мы сравниваем строки по очереди с #1...#n
до тех пор, пока не достигнем необходимого количества совпадающих слов.Если какие-либо слова не совпадают (я использовал /i
, чтобы сделать сравнение без учета регистра), тогда обработка этого имени файла прекращается.После сопоставления необходимого количества слов создается требуемый каталог (2> nul подавляет сообщение об ошибке при условии, что проблема «каталог уже существует») и файл перемещается в требуемый подкаталог.
Обратите внимание, чтоmd
является активным, поэтому каталоги будут созданы, но команда move
просто echo
введена в целях безопасности.Удалите ключевое слово echo
здесь, чтобы фактически переместить файл ...
Примечание: исправлено - комментарий "сколько слов .." должен быть условным REM
, а не ::
, так как метки не допускаются в пределахцикл for
(за исключением случаев, которые были опубликованы другими после похвальных обширных исследований, но я не собираюсь устраивать, так как одеяло «всегда используй rem
» всегда работает)