Пакетный файл для пересечения размера ссылки и переименования 1300 файлов, которые потеряли свои имена - PullRequest
0 голосов
/ 09 июля 2019

Я недавно (случайно) отформатировал жесткий диск, содержащий около 2000 важных архивных файлов. Я использовал одно программное обеспечение для восстановления данных, которое восстановило файлы, но ни одно из имен (Все с названием «LostFile_1, LostFile2 ... и т. Д.»), И второе программное обеспечение, которое восстановило все имена, но все файлы были повреждены и не будут открыт.

Мы находимся в середине кода, который перекрестно ссылается на собственные имена из поврежденных файлов и сопоставляет их с отсутствующими файлами имен (LostFile и т. Д.) В зависимости от размера файла.

Есть 2 папки, одна с именем «RealFiles», которая имеет общие имена «LostFile», но рабочие файлы, и вторая папка «RealNames», которая содержит настоящие имена, но неработающие файлы. Мы сопоставляем размеры файлов, которые совпадают, и извлекаем имена из файлов "RealNames", чтобы переименовать соответствующие, не поврежденные "RealFiles".

Я очень близок благодаря коду из комментария Бена Персонака ниже (спасибо!), Это почти решает проблему, журнал показывает, что он настроен на переименование всех файлов, но выходной файл только в «Hard_Linked» переименовывает и создает файл для первого совпадения.

Код для переименования и перекрестная ссылка (Credit Ben Personick):

  @(
    SetLocal EnableDelayedExpansion
    Echo off
    Set "_Src=C:\Path\Lost"
    Set "_Ref=C:\Path\Reference"
    Set "_Lnk=C:\Path\Hard_Linked"
    Set "_Dst=C:\Path\Renamed"
    Set "_Log=C:\Path\Rename.log"
  )

 Set "_J=0"
 For /F "Tokens=*" %%A in ('
   Dir /A-D /B /OSE "%_Src%"
 ') Do (
   Set "_SrcFile!_J!=%%A"
   Set /A "_J+=1"
 )

 Set /A "_J-=1"

 Set "_I=0"
 For /F "Tokens=*" %%A in ('
   Dir /A-D /B /OSE "%_Ref%"
 ') Do (
  Call ECHO.Rename: "%%_SrcFile!_I!%%" - To: "%%A"
  Call ECHO.Rename: "%%_SrcFile!_I!%%" - To: "%%A">>"%_Log%"
  REM Comment the next line to stop maiing hardlinks
  CALL MkLink /H "%_Lnk%\%%A" "%_Src%\%%_SrcFile!_I!%%"
   REM Un-comment the next line to move files to final folder renamed
  REM CALL MOVE /Y "%_Src%\%%_SrcFile!_I!%%" "%_Dst%\%%A"
   Set /A "_I+=1"
  )

 (
   Endlocal
   Exit /b
 )

Журнал:

Rename: "LostFile_1.file" - To: "Correct Name 1.file"
Rename: "LostFile_2.file" - To: "Correct Name 2.file"
Rename: "LostFile_3.file" - To: "Correct Name 3.file"
Rename: "LostFile_4.file" - To: "Correct Name 4.file"
Rename: "LostFile_5.file" - To: "Correct Name 5.file"

Результат в папке Hard_Linked: LostFile1 правильно создан и переименован в собственное имя, но не в 2, 3, 4, 5.

Ответы [ 2 ]

1 голос
/ 09 июля 2019
  • Создание (псевдо) массива с размером [123] в качестве имени и имени файла в качестве значения путем итерации реальных имен файлов.

  • Затем выполните итерацию LostFiles и проверьте, существует ли соответствующий размер, и переименуйте.

Протестировано и улучшено:

:: Q:\Test\2019\07\09\SO_56946186.cmd
@Echo off & setlocal EnableDelayedExpansion
Set "RealNames=A:\Test\RealNames\*"
Set "RealFiles=A:\Test\RealFiles\LostFile_*"

for %%N in ("%RealNames%") do set "size[%%~zN]=%%~fN"
:: set size
for %%F in ("%RealFiles%") do if defined size[%%~zF] (
    for %%n in ("!size[%%~zF]!") do (
        Ren "%%F" "%%~nn_Fixed%%~xn" && Del "%%~fn"
    )
) else (
    echo no matching size[%%~zF] for %%F
)

Команда переименования только отображается, удалите эхо для do переименования.

Dir листинг до:

> gci A:\Test\* -Recurse
    Verzeichnis: A:\Test\RealFiles

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2018-11-13     07:52              0 LostFile_1
-a----       2016-11-18     17:12            878 LostFile_2
-a----       2018-01-27     16:17           9811 LostFile_3
-a----       2016-12-10     19:53            435 LostFile_4
-a----       2019-05-27     23:50              2 LostFile_5
-a----       2019-05-27     23:50              7 LostFile_6
-a----       2017-08-18     17:05            985 LostFile_7
-a----       2017-03-21     16:24           1086 LostFile_8
-a----       2017-03-21     16:24           3002 LostFile_9

    Verzeichnis: A:\Test\RealNames

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2018-11-13     07:52              0 1099511627776
-a----       2016-11-18     17:12            878 Choose-CUI.ps1
-a----       2018-01-27     16:17           9811 ConvertTo-Expression.ps1
-a----       2016-12-10     19:53            435 Enum-SpecalFolders.vbs
-a----       2019-05-27     23:50              2 ESC.bin
-a----       2019-05-27     23:50              7 ESC.hex
-a----       2017-08-18     17:05            985 Get-Date.cmd
-a----       2017-03-21     16:24           1086 Get-High20Proc.ps1
-a----       2017-03-21     16:24           3002 High20Proc.html

А после запуска партии:

> gci A:\Test\* -Recurse

    Verzeichnis: A:\Test\RealFiles

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2018-11-13     07:52              0 1099511627776_Fixed
-a----       2016-11-18     17:12            878 Choose-CUI_Fixed.ps1
-a----       2018-01-27     16:17           9811 ConvertTo-Expression_Fixed.ps1
-a----       2016-12-10     19:53            435 Enum-SpecalFolders_Fixed.vbs
-a----       2019-05-27     23:50              2 ESC_Fixed.bin
-a----       2019-05-27     23:50              7 ESC_Fixed.hex
-a----       2017-08-18     17:05            985 Get-Date_Fixed.cmd
-a----       2017-03-21     16:24           1086 Get-High20Proc_Fixed.ps1
-a----       2017-03-21     16:24           3002 High20Proc_Fixed.html
1 голос
/ 09 июля 2019

Хорошо, на самом деле это довольно просто в cmd.

Но давайте сделаем еще один шаг вместо того, чтобы все в одном, вставим оба в два.

Также я бы предложилзапустив журнал того, что будет сначала переименовано для просмотра, и / или скопировав файлы в 3-й каталог для проверки, чтобы убедиться, что вы получили желаемые результаты.

Так как вы не знакомы с cmd / пакетными сценариямиХочу заметить, что у нас есть несколько вариантов итерации файлов, наиболее удобные for, for/F и Forfiles - обычное средство для циклического перемещения файлов, иногда с DIR cmd вfor /F в качестве альтернативы со списком файлов WMIC (хотя, к счастью, WMIC, наконец, становится более ограниченным в пользу Powershell).

Если вы хотите просто предположить, что каждый файл будет правильным на основе совпадения размеров и размеровточно и не дублируются, и вы в этом достаточно уверены, тогда использование dir cmd для сортировки по размеру будет прагматичным методом быстрого сопоставления

Если большеeds, которые должны быть сделаны при сопоставлении, тогда цикл for или forfiles был бы лучшей альтернативой

Чтобы сэкономить место в этом процессе, вместо копирования мы можем создать жесткие ссылки, затем вы можете проверить их работу,при условии, что они это делают, вы можете удалить жесткие ссылки и использовать команду Move, чтобы переименовать их.

  @(
    SetLocal EnableDelayedExpansion
    Echo off
    Set "_Src=C:\Ren\Lost"
    Set "_Ref=C:\Ren\Reference"
    Set "_Lnk=C:\Ren\Hard_Linked"
    Set "_Dst=C:\Ren\Renamed"
    Set "_Log=C:\Ren\Rename.log"
  )

 Set "_J=0"
 For /F "Tokens=*" %%A in ('
   Dir /A-D /B /OSE "%_Src%"
 ') Do (
   Set "_SrcFile!_J!=%%A"
   Set /A "_J+=1"
 )

 Set "_I=0"
 For /F "Tokens=*" %%A in ('
   Dir /A-D /B /OSE "%_Ref%"
 ') Do (
   Call ECHO.Rename: "%%_SrcFile!_I!%%" - To: "%%A"
   Call ECHO.Rename: "%%_SrcFile!_I!%%" - To: "%%A">>"%_Log%"
   REM Comment the next line to stop maiing hardlinks
    CALL MkLink /H "%_Lnk%\%%A" "%_Src%\%%_SrcFile!_I!%%"
   REM Un-comment the next line to move files to final folder renamed
    REM CALL MOVE /Y "%_Src%\%%_SrcFile!_I!%%" "%_Dst%\%%A"
   Set /A "_I+=1"
  )

 (
   Endlocal
   Exit /b
 )

Я объясню это немного позже, но придется выполнить атм.

У меня была возможность вернуться к объявлению, хотя я сейчас не могу тратить время на объяснения из-за напряженного рабочего дня. Я исправил одну ошибку, добавив Set /A "_I+=1", из-за чего значение теста не увеличилось.файл каждый раз.


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

Y:\>C:\Ren\RenameScript.cmd
Rename: "SomethingOld.ext1" - To: "ReferenceFileCorect_A_Unique1.ext1"
Hardlink created for C:\Ren\Hard_Linked\ReferenceFileCorect_A_Unique1.ext1 <<===>> C:\Ren\Lost\SomethingOld.ext1
Rename: "SomethingOld.txt" - To: "ReferenceFileCorect_A_New_name.txt"
Hardlink created for C:\Ren\Hard_Linked\ReferenceFileCorect_A_New_name.txt <<===>> C:\Ren\Lost\SomethingOld.txt
Rename: "SomethingOld3.txt" - To: "ReferenceFileCorect_A_ThirdName.txt"
Hardlink created for C:\Ren\Hard_Linked\ReferenceFileCorect_A_ThirdName.txt <<===>> C:\Ren\Lost\SomethingOld3.txt

Это сообщение: Hardlink created for C:\Ren\Hard_Linked\ReferenceFileCorect_A_Unique1.ext1 <<===>> C:\Ren\Lost\SomethingOld.ext1 - это вывод MKLink, если вы не видите этого в приглашении CMD, то, скорее всего, вы не запустили сценарий CMD в административном приглашении cmd.

Мы можем добавить код в сценарий для вызоваPowerShell и перезапустите себя вадминистративный запрос cmd, но он будет менее мутным, если вы сделаете это непосредственно для тестирования, поскольку это не является частью вашего исходного Q.

Так что я хотел бы потратить минуту, чтобы объяснить, что такое сценарийделаю и почему для вас, так что вы можете идти вперед самостоятельно:

 SetLocal EnableDelayedExpansion

Мы включаем Delayed Expansion, чтобы мы могли легко оценить содержимое переменных внутри цикла for, ссылаясь на них с помощью !_var! вместо %_Var%, технически мы можем обойтись без этого, если в любом из ваших имен файлов есть !, мы должны отключить это и немного переписать, если нет, то все нормально.

 ECHO OFF

Я не позволяю скрипту отображать каждую строку, которую он делает, поэтому у нас меньше загроможденных выходных данных.

Установка переменных не требует пояснений

это позволяет нам легко зацикливать переменные иобновить их содержимое в цикле без использования CALL.

 Set "_J=0"
 For /F "Tokens=*" %%A in ('
   Dir /A-D /B /OSE "%_Src%"
 ') Do (
   Set "_SrcFile!_J!=%%A"
   Set /A "_J+=1"
 )

Здесь я использую DIR, чтобы быстро отсортировать файлы по их размеру и расширению, aи вернуть только имена файлов.DIR делает это очень быстро, поэтому предпочтительно, если вы выполняете небольшую сортировку, а не сопоставляете файлы, используя сравнение IF позже.

Опция /A-D игнорирует каталоги /B будет выводить только имя файла (поскольку мы не выполняем рекурсивный анализ) /OSE - /O означает "Упорядочить по", параметры S и E сортируют по размеру, а затем по расширению файла, поэтому даже если два файла имеют одинаковый размер, если их расширение отличаетсяпорядок сортировки будет таким же.

Все это помещается в For /F цикл, который является способом для анализа вывода команды, мы используем "Tokens=*", чтобы убедиться, что мы берем все не белыеВозвращаемое пространство и помещаем его в переменную.

В разделе DO () мы увеличиваем временную переменную _J, а затем создаем псевдомассив в памяти, создавая переменные, которые используют значение _J дляхранить значение каждого файла, возвращаемого командой DIR в цикл.Set "_SrcFile!_J!=%%A"

 Set "_I=0"
 For /F "Tokens=*" %%A in ('
   Dir /A-D /B /OSE "%_Ref%"
 ') Do (
   Call ECHO.Rename: "%%_SrcFile!_I!%%" - To: "%%A"
   Call ECHO.Rename: "%%_SrcFile!_I!%%" - To: "%%A">>"%_Log%"
   REM Comment the next line to stop maiing hardlinks
    CALL MkLink /H "%_Lnk%\%%A" "%_Src%\%%_SrcFile!_I!%%"
   REM Un-comment the next line to move files to final folder renamed
    REM CALL MOVE /Y "%_Src%\%%_SrcFile!_I!%%" "%_Dst%\%%A"
   Set /A "_I+=1"
  )

Теперь мы снова зациклим вывод DIR, на этот раз в справочном каталоге, и так как набор файлов такой же, порядок будет таким же, как процесс в первой итерации цикла, и будут возвращены только именабудет отличаться (т.е. именно то, что мы хотим).

В пределах DO () здесь мы получаем каждый результат от DIR, отправляем его в CLI, выводим в журнал, используя перенаправление >>, изатем создайте наши жесткие ссылки или переименуйте файлы, используя MOVE (если вы откомментируете строку, удалив «REM»)

(обратите внимание, если бы мы собирались отображать и регистрировать несколько строк, я бы использовал CALLподфункции, чтобы сделать это, чтобы не было повторяющихся строк, однако, поскольку я решил оставить все как есть только один раз

Поскольку порядок один и тот же, я знаю, чтоитерация, на которой мы работаем, нам не нужно выполнять какие-либо операции сравнения (медленные), пока мы уверены, что дупликов не существует.

Я решил создать здесь жесткие ссылки, потому что их будет почтинет перегреваd при их создании, и они позволяют вам проводить живые тесты, чтобы точно определить, как выглядят файлы, прежде чем перемещать их для переименования, что является лучшим из всех миров)

Запуск в аналогичныхситуации, в которых я находился, и работая вручную (в детстве), могу сказать, что хотел бы знать этот трюк 20 лет назад, чтобы сэкономить время и диск при тестировании файлов.

MKLINK - этонаходка для такого рода вещей.Теперь у вас есть скорость операции MOVE, но вы можете воспользоваться преимуществами копии, чтобы избежать случайного переименования их и возникновения проблем в ваших реальных исходных файлах.

Если вы удовлетворены результатами,Вы можете удалить все жесткие ссылки, REM из создания жестких ссылок и снять комментарий со строки MOVE, которая должна постоянно переименовывать их.Тогда просто убедитесь, что в конце удалите ваши справочные файлы, чтобы случайно не сохранить плохой файл, который вы хотите сохранить.

Это

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...