Вопрос или проблема
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
Некоторое дальнейшее чтение:
-
Использование: Команды с перенаправлением
|
,<
,>
,2>
,2>&1
, и т.д.
Ответ или решение
Для решения вашей задачи по удалению ненужных файлов .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
Пояснение кода:
-
Установка каталога: В строке
set "Folder=..."
замените путь на ваш локальный путь к директории, где находятся ваши видео- и .idx файлы. -
Перебор файлов: Используя цикл
for
, скрипт перебирает каждый файл с расширением.idx
. -
Обработка имени файлов:
- Получает имя файла без расширения и убирает
.idx
, а затем.mts
. - Это осуществляется через команду
set
, что позволяет манипулировать строками.
- Получает имя файла без расширения и убирает
-
Проверка наличия файла: После обработки имени, команда
if not exist
проверяет, существует ли соответствующий видеофайл. - Удаление: Если видеофайл не существует, выполняется команда
del
, и ненужный файл.idx
удаляется.
Как использовать скрипт:
- Создайте текстовый файл с расширением
.bat
, например,delete_orphaned_idx.bat
. - Скопируйте и вставьте указанный код в этот файл.
- Запустите скрипт, дважды щелкнув по нему. Он выполнит поиск и удаление ненужных
.idx
файлов в указанной папке.
Таким образом, при использовании данного скрипта, удаление файлов будет происходить только для тех .idx
, которые не имеют соответствующих им .mts
, что помогает избежать случайного удаления нужных данных.