Windows пакет для сравнения имен файлов с частичным несовпадением

Вопрос или проблема

Windows пакет для сравнения имен файлов с частичным несовпадением

У меня есть каталог с видеофайлами и соответствующими (скрытыми) .idx файлами. При удалении любого видеофайла соответствующие .idx файлы остаются. Я хочу периодически удалять эти “несвязанные” .idx файлы.

Скрипт пакетной обработки ниже позволяет это сделать, но он работает только тогда, когда имя .idx файла совпадает с именем видеофайла. То есть: One.mts и One.idx.
Проблема в том, что при создании .idx файлов к их имени добавляется расширение видеофайла. Следовательно, у меня есть One.mts и One.mts.idx.

Как я могу заставить код сравнивать два имени, игнорируя дополнительное добавленное расширение в .idx файле.
Лучшим решением было бы, если бы я мог заставить код игнорировать часть .idx файла, при этом все еще сравнивая эти два файла. Это позволило бы хранить другие типы видео в том же каталоге без удаления их .idx файлов, потому что они не совпадали с именем видеофайла .mts (как мне кажется).

Для справки: тот факт, что .idx файлы скрыты, не является проблемой в коде ниже.

@echo off
   echo.
   echo.

for %%F in ("*.idx") do @if not exist "%%~nF.mts" echo "%%F"
   echo.
   echo.

set /p my_var= Нажмите ENTER, чтобы удалить... Нажмите X, чтобы отменить

   for %%F in (*.idx) do @if not exist "%%~nF.mts" del "%%F"

Вы могли бы сделать что-то подобное, если соответствующий видеофайл не найден, скрипт спросит, хотите ли вы удалить idx (файл/файлы)…

@echo off

:: Указать папку, где находятся видео и.idx файлы:
set Folder=%userprofile%\desktop\Teste

echo Хотите ли вы удалить эти файлы?

for /f "tokens=*" %%a in ('dir /b "%Folder%\*.idx"') do for /f "tokens=*" %%b in ("%%~na") do if not exist "%Folder%\%%~na.mts" if not exist "%Folder%\%%~nb.mts" echo %%a

set /p "Option=Нажмите X для удаления: "
IF /i "%Option%"=="x" goto :Delete

exit

:Delete
for /f "tokens=*" %%a in ('dir /b "%Folder%\*.idx"') do for /f "tokens=*" %%b in ("%%~na") do if not exist "%Folder%\%%~na.mts" if not exist "%Folder%\%%~nb.mts" del /q "%Folder%\%%a"
exit

Просто чтобы убедиться, что я правильно понял ваш вопрос, даже с моими когнитивными трудностями в языках, отличных от моего родного…

Предположим, что у меня есть папка со следующими файлами…

.\001.mts.idx
.\002.idx
.\002.mts
.\003.mts.idx
.\004.idx
.\004.mts
.\005.mts.idx
.\006.idx
.\006.mts
.\007.mts.idx
.\008.idx
.\008.mts
.\009.mts.idx
.\010.idx
.\011.mts.idx
.\012.idx

Чтобы создать эти файлы для моих тестов, я создал их в пустой папке и запустил bat-файл ниже:

@echo off

cd /d "%~dp0"

>.\001.mts.idx   echo/001.mts.idx
>.\002.idx       echo/002.idx
>.\002.mts       echo/002.mts
>.\003.mts.idx   echo/003.mts.idx
>.\004.idx       echo/004.idx
>.\004.mts       echo/004.mts
>.\005.mts.idx   echo/005.mts.idx
>.\006.idx       echo/006.idx
>.\006.mts       echo/006.mts
>.\007.mts.idx   echo/007.mts.idx
>.\008.idx       echo/008.idx
>.\008.mts       echo/008.mts
>.\009.mts.idx   echo/009.mts.idx
>.\010.idx       echo/010.idx
>.\011.mts.idx   echo/011.mts.idx
>.\012.idx       echo/012.idx

Теперь с этими файлами в папке, не будучи уверенным в их цели или сценарии, я попробовал использовать цикл for /f, фильтруя только файлы where any_name.mts.idx, это потому что команда where может перечислять файлы в этом формате, явно указав имена для использования подстановки в формате *.mts.idx.

Поскольку я уже получаю имена интересующих файлов в цикле, мне просто нужно использовать условие несуществующего файла, чтобы выполнить действие удаления вашего орфанного файла, так что, если файл current_name.mts не существует, я понимаю, что его нужно удалить current_name.mts.idx

@echo off && setlocal

cd /d "%~dp0"

for /f delims^= %%G in =;(' @"%__AppDir__%where.exe" .:*.mts.idx
   ');= do call set "_name=%%~nG" && call %:^) "%%_name:.idx=%%"

%:^)
if "%~1" == "" =;(
     "%windir%\System32\timeout.exe" -1 | endlocal & goto :eOf
    );= else if not exist ".\%~1" =;(
        echo/Удаление ".\%~1.idx" - файл ".\%~n1.mts" не найден!..
        @del /q /f /a ".\%~1.idx" & exit /b
    );= 

exit /b 
  • Вывод пакетной обработки // по echo/Удаление ".\%~1" ... :
Удаление ".\001.mts.idx" - файл ".\001.mts" не найден!..
Удаление ".\003.mts.idx" - файл ".\003.mts" не найден!..
Удаление ".\005.mts.idx" - файл ".\005.mts" не найден!..
Удаление ".\007.mts.idx" - файл ".\007.mts" не найден!..
Удаление ".\009.mts.idx" - файл ".\009.mts" не найден!..
Удаление ".\011.mts.idx" - файл ".\011.mts" не найден!..

Это касается только части удаления несовпадающих файлов, где в имени есть AnyName.mts.idx, но если вы сфокусированы на получении ответа для удаления орфанных имен any.idx и/или any.mts.idx. Тогда вам нужно будет использовать два цикла For /F, второй с конкретным фильтром, чтобы не обрабатывать появления имени *.mts.idx, который можно получить с помощью find /aVoid

@echo off && setlocal

cd /d "%~dp0"

for /f usebackq^delims^= %%G in =;(
    `"%windir%\System32\where.exe" .:*.mts.idx`
    );= do call set "_name=%%~nG" && call %:^) "%%_name:.idx=%%"

%:^)
if "%~1" == "" goto %:^(

if not exist ".\%~1" =;(
     echo/Удаление ".\%~1.idx" - файл "%~1" не найден!..
     @del /q /f /a ".\%~1.idx" & exit /b
    );= else goto :eOf

%:^(
for /f usebackq^delims^= %%i in =;(
    `call "%windir%\System32\where.exe" .:*.idx ^| "%windir%\System32\find.exe" /v /i ".mts.idx"`
    );= do if not exist ".\%%~ni.mts" =;(
          echo/Удаление ".\%%~ni.idx"     - файл ".\%%~ni.mts" не найден!..
          @del /q /f /a ".\%%~ni.idx"
        );=

"%windir%\System32\timeout.exe" -1 | endlocal & goto :eOf 
  • Вывод пакетной обработки // по echo/Удаление ".\%~1.idx" |или| ".\%%~ni.idx" ... :
Удаление ".\001.mts.idx" - файл ".\001.mts" не найден!..
Удаление ".\003.mts.idx" - файл ".\003.mts" не найден!..
Удаление ".\005.mts.idx" - файл ".\005.mts" не найден!..
Удаление ".\007.mts.idx" - файл ".\007.mts" не найден!..
Удаление ".\009.mts.idx" - файл ".\009.mts" не найден!..
Удаление ".\011.mts.idx" - файл ".\011.mts" не найден!..
Удаление ".\010.idx"     - файл ".\010.mts" не найден!..
Удаление ".\012.idx"     - файл ".\012.mts" не найден!..

  • Примечание: Обратите внимание на использование cd /d "%~dp0", так как таким образом скрипт переходит и работает внутри папки, где находится сам скрипт. Если вы сохраните пакетный файл в другой папке, отличной от папки, в которой вы будете тестировать и/или выполнять действия по удалению ваших файлов, то замените ее на полный путь к папке, где находятся файлы *.mts, *.idx, *mts.idx.
@echo off && setlocal

cd /d "D:\Полный\Путь\К\Где\Находятся\Ваши\Файлы"
...

1. Определите, что возвращать в команде вывода For /F "Delims=" .. (cmd), без разделителей, чтобы использовать всю строку вывода.

...

for /f delims^= %%G in (' ...
   ');= do ...

2. Как уже упоминалось, where .:*.mts.idx вернет только файлы, которые явно имеют формат имени, соответствующий подстановочному знаку "любой файл в текущей папке = * " + ".Строка1" + ".Строка2".

...
for /f ... (' @"%__AppDir__%where.exe" .:*.mts.idx ') do ... 

3. Используйте call set _varible=File_Name, чтобы определить имя перечисленного файла в текущей переменной %~file_Name_from_G (%%~nG) в цикле, используйте call set для определения имени файла, перечисленного в текущей переменной в цикле, а затем используйте call :Lable %%_variable_defined_and_already_expanded_on_the_same_line:SubString_remove/replace_String[.IDX]=[Nothing]% для %_name:.idx=[НИЧЕГО!!!]%:

...

for /f ( ... 
   ) do call set "_name=%%~nG" && call %:^) "%%_name:.idx=%%"

4. Ваш поток войдет в :Label дважды, первый раз через вызов call :Label, где передается аргумент 1 (%1) "%%_name:.idx=%%", и во второй момент, когда цикл завершает перечисление файлов в цикле For /F, в этот момент вызова :Lable не будет, и, следовательно, передача аргумента %1 не будет истинной. Под истинным условием будет удовлетворено вызов + аргумент 1, а ложное условие будет удовлетворено, когда не будет вызова и не будет передан аргумент в том же событии обработки, таким образом, приходя к :Label в порядке строки в пакетном файле.

Когда :Label не вызывается, он переходит к :Secound_Label, если он вызывается, то он сам проверяет наличие Current_File_Name.mts, и если он не существует, возвращает расширение .idx, чтобы удалить имя отправленного файла, в форме удалить Current_File_Name.mts.idx, и выходит/возвращает из вызванного :Label с помощью goto :End_Of_File (что эквивалентно exit /b), и аналогично в этом if, если файл существует, он выходит на ) else goto :eof

...

:Lable
if "%~1" == "" ( 
     goto :Secound_Label
   ) else if not exist ".\%~1" (
     echo/Удаление ".\%~1.idx" - файл "%~1" не найден!..
     @del /q /f /a ".\%~1.idx" & exit /b
    );= else goto :eOf 


5. :Secound_Label будет использовать ту же механику/логику, что и первый :Lable, но отфильтровывает уже обработанные файлы в первом цикле For /F, используя фильтр в перенаправлении | FindString /aVoid ЛюбойФайлЧтоСодержит_ИмяС[.mts.idx], таким образом, ограничивая выполнение только для файлов Name_Any[.idx], и когда ни один “.idx orphan file” не найден, он будет операцией исключения…

...

:Secound_Label
for /f usebackq^delims^= %%i in =;(
    `call "%windir%\System32\where.exe" .:*.idx ^| "%windir%\System32\find.exe" /v /i ".mts.idx"`
    );= do if not exist ".\%%~ni.mts" =;(
          echo/Удаление ".\%%~ni.idx"     - файл ".\%%~ni.mts" не найден!..
          @del /q /f /a ".\%%~ni.idx"
        );=

6. timeout -1 – это пауза, пропускающая вывод с обычным текстом Нажмите любую клавишу для продолжения ... и ожидая выполнения команд, добавляя канала (перенаправление) | заканчивает Setlocal (с помощью Endlocal) и переходит в конец файла, завершая выполнение пакетного файла, но при этом останавливается на столько времени, сколько пользователь считает необходимым, чтобы увидеть текст, отображающий названия файлов, исключенных в предыдущих действиях.

...

"%windir%\System32\timeout.exe" -1 | endlocal & goto :eOf 

Некоторое дальнейшее чтение:

Ответ или решение

Для решения вашей задачи по удалению ненужных файлов .idx, которые не имеют соответствующих видеофайлов .mts, можно воспользоваться следующей пакетной скриптовой программой. Скрипт будет сравнивать имена файлов, игнорируя суффиксы, что позволит избежать удаления нужных файлов, связанных с другими форматами видео.

Вот пример скрипта:

@echo off
setlocal

:: Укажите папку с видео и .idx файлами
set "Folder=%userprofile%\desktop\Teste"

echo Проверка файлов на наличие соответствия...

:: Перебираем все .idx файлы в заданной папке
for %%F in ("%Folder%\*.idx") do (
    :: Получаем имя файла без расширения и удаляем .mts.idx
    set "fileName=%%~nF"
    set "baseName=!fileName:.idx=!"
    set "baseName=!baseName:.mts=!"

    :: Проверяем, существует ли соответствующий видеофайл
    if not exist "%Folder%\!baseName!.mts" (
        echo Удаление ненужного файла: %%F
        del /q "%%F"
    )
)

echo Завершено. Удалены ненужные файлы .idx.
endlocal

Пояснение кода:

  1. Установка каталога: В строке set "Folder=..." замените путь на ваш локальный путь к директории, где находятся ваши видео- и .idx файлы.

  2. Перебор файлов: Используя цикл for, скрипт перебирает каждый файл с расширением .idx.

  3. Обработка имени файлов:

    • Получает имя файла без расширения и убирает .idx, а затем .mts.
    • Это осуществляется через команду set, что позволяет манипулировать строками.
  4. Проверка наличия файла: После обработки имени, команда if not exist проверяет, существует ли соответствующий видеофайл.

  5. Удаление: Если видеофайл не существует, выполняется команда del, и ненужный файл .idx удаляется.

Как использовать скрипт:

  1. Создайте текстовый файл с расширением .bat, например, delete_orphaned_idx.bat.
  2. Скопируйте и вставьте указанный код в этот файл.
  3. Запустите скрипт, дважды щелкнув по нему. Он выполнит поиск и удаление ненужных .idx файлов в указанной папке.

Таким образом, при использовании данного скрипта, удаление файлов будет происходить только для тех .idx, которые не имеют соответствующих им .mts, что помогает избежать случайного удаления нужных данных.

Оцените материал
Добавить комментарий

Капча загружается...