none
Обрезание длинных путей RRS feed

  • Вопрос

  • Решили в компании пойти жесткими методами и обрезать длинные название путей. Уменьшать длину папок до 20 символов. 
    Использую ChildItem для поиска путей, что удобно, он изначально выводит первую по глубине папку, потом подпапку и т.д. до файла.
    Что позволяет, если переименовать первую папку, то глубже папки и файлы возможно уже не надо будет трогать.
    Но возникла другая проблема, вот мой код

    $fileList=Get-ChildItem -LiteralPath $pathfolder2 -Recurse | Where-Object {$_.FullName.Length -gt 260 } foreach ($textfile in $fileList) {
    $filePath = $textfile.fullname
    $string = Split-Path $filePath -Leaf
    $truncated = $string.Remove(20)
    Rename-Item -LiteralPath $filePath  -NewName $truncated

    }

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

    2 апреля 2021 г. 9:05

Все ответы

  • Здравствуйте.

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


    Alexandr_Smirnoff

    2 апреля 2021 г. 22:41
  • Можно конечно и так, если в основном это файлы, так как может быть к примеру так:

    было:

    Папка1\Длинная папка 2\Длинная Папка 3\файл
    Папка1\Длинная папка 2\Папка 4\файл

    к примеру переименовал папку 3, папку 2 и длина стала нормальной, переходит к следующей строке, а там уже папка 2 имеет новое имя, а скрипт это не знает и получается ошибка. Другое дело, что скорее всего длина пути уже будет иметь нормальное значение.

    3 апреля 2021 г. 12:19
  • Можно конечно и так, если в основном это файлы, так как может быть к примеру так:

    было:

    Папка1\Длинная папка 2\Длинная Папка 3\файл
    Папка1\Длинная папка 2\Папка 4\файл

    к примеру переименовал папку 3, папку 2 и длина стала нормальной, переходит к следующей строке, а там уже папка 2 имеет новое имя, а скрипт это не знает и получается ошибка. Другое дело, что скорее всего длина пути уже будет иметь нормальное значение.

    Да, в том и дело, что после переименования Папки 3 надо не переименовывать Папку 2, а продолжить переименование внутри Папки 2. И только тогда, когда в ней подпапки все пройдены, переименовывать Папку 2

    Alexandr_Smirnoff

    3 апреля 2021 г. 12:33
  • Тогда ситуация другая

    Папка1\Длинная папка 2\Длинная Папка 3\файл длина1
    Папка1\Длинная папка 2\Длинная Папка 3\файл2
    Папка1\Длинная папка 2\Папка 4\файл3

    Делаем поиск длинных путей, get-childitem получаю эти три строчки, выбираю максимальный путь, файл длина1. Из этого пути получаю максимальный путь до файла: Папка1\Длинная папка 2\Длинная Папка 3\
    Теперь опять через get-childitem ищу все длинный файлы, но уже путь ставлю Папка1\Длинная папка 2\Длинная Папка 3\ эти файлы я переименовываю при необходимости, потом переименовываю Длинная папка 3, но дело в том, что в первом get-childitem все равно осталась информацию до файла 2 и он попытается его найти.

    $fileList=Get-ChildItem -LiteralPath $pathfolder2 -Recurse -File | Where-Object {$_.FullName.Length -gt $maxpath } | Sort-Object {$_.FullName.Length} -Descending
    
    foreach ($textfile in $fileList) {
      $filePath = $textfile.fullname #получаем полный путь с файлом
      $path = Split-Path $filePath -Parent #получаем полный путь до файла
      
      $fileListfolder=Get-ChildItem -LiteralPath $path -Recurse -File | Where-Object {$_.FullName.Length -gt $maxpath } #ищем все длинные файлы в подпапке
      
    	foreach ($textfilefolder in $fileListfolder) {
    	
    		тут обрезаем имя файла если надо  
      
    	}
    }

    3 апреля 2021 г. 13:42
  • учтите только в скрипте что при обрезке можно получить неуникальные названия из уникальных

    c:\long path 1\ и c:\long path 2\ могут быть обрезаны до c:\long\ что полностью может поломать структуру


    The opinion expressed by me is not an official position of Microsoft

    3 апреля 2021 г. 16:32
    Модератор
  • Тогда ситуация другая

    Папка1\Длинная папка 2\Длинная Папка 3\файл длина1
    Папка1\Длинная папка 2\Длинная Папка 3\файл2
    Папка1\Длинная папка 2\Папка 4\файл3

    Делаем поиск длинных путей, get-childitem получаю эти три строчки, выбираю максимальный путь, файл длина1. Из этого пути получаю максимальный путь до файла: Папка1\Длинная папка 2\Длинная Папка 3\
    Теперь опять через get-childitem ищу все длинный файлы, но уже путь ставлю Папка1\Длинная папка 2\Длинная Папка 3\ эти файлы я переименовываю при необходимости, потом переименовываю Длинная папка 3, но дело в том, что в первом get-childitem все равно осталась информацию до файла 2 и он попытается его найти.

    $fileList=Get-ChildItem -LiteralPath $pathfolder2 -Recurse -File | Where-Object {$_.FullName.Length -gt $maxpath } | Sort-Object {$_.FullName.Length} -Descending
    
    foreach ($textfile in $fileList) {
      $filePath = $textfile.fullname #получаем полный путь с файлом
      $path = Split-Path $filePath -Parent #получаем полный путь до файла
      
      $fileListfolder=Get-ChildItem -LiteralPath $path -Recurse -File | Where-Object {$_.FullName.Length -gt $maxpath } #ищем все длинные файлы в подпапке
      
    	foreach ($textfilefolder in $fileListfolder) {
    	
    		тут обрезаем имя файла если надо  
      
    	}
    }

    А если после обрезки имени файла повторить get-childitem для поиска длинных имен файлов? Чтоб создать "обновленный" массив.

    Alexandr_Smirnoff

    3 апреля 2021 г. 19:57
  • учтите только в скрипте что при обрезке можно получить неуникальные названия из уникальных

    c:\long path 1\ и c:\long path 2\ могут быть обрезаны до c:\long\ что полностью может поломать структуру


    The opinion expressed by me is not an official position of Microsoft

    Да, тут полностью согласен с Вами. Например, системные ProgramFiles и ProgramData в формате "8.3" станут выглядет одинаково по именам... 

    Это можно попробовать обойти, формируя Короткое имя папки=Длинное имя папки, урезанное до Х символов+одна/две последние буквы из Длинного имени папки. На примере ProgramFiles и ProgramData это получится Programs и Programa. Конечно, об "удобочитаемости" тут речи уже быть не может, но так хоть уникальность имени сохраняется.


    Alexandr_Smirnoff

    3 апреля 2021 г. 20:06
  • Да, тут полностью согласен с Вами. Например, системные ProgramFiles и ProgramData в формате "8.3" станут выглядет одинаково по именам... 

    Это можно попробовать обойти, формируя Короткое имя папки=Длинное имя папки, урезанное до Х символов+одна/две последние буквы из Длинного имени папки. На примере ProgramFiles и ProgramData это получится Programs и Programa. Конечно, об "удобочитаемости" тут речи уже быть не может, но так хоть уникальность имени сохраняется.


    Alexandr_Smirnoff

    имхо, тут происходит изобретание велосипеда который уже существует


    The opinion expressed by me is not an official position of Microsoft

    • Предложено в качестве ответа Alexandr_Smirnoff 3 апреля 2021 г. 23:47
    3 апреля 2021 г. 22:48
    Модератор
  • Alexandr_Smirnoff

    имхо, тут происходит изобретание велосипеда который уже существует


    The opinion expressed by me is not an official position of Microsoft

    Да, действительно. Но велосипед был спрятан) Спасибо, что нашли его.

    Alexandr_Smirnoff

    3 апреля 2021 г. 23:47
  • учтите только в скрипте что при обрезке можно получить неуникальные названия из уникальных
    
    c:\long path 1\ и c:\long path 2\ могут быть обрезаны до c:\long\ что полностью может поломать структуру

    Да, проверку на наличие таких уже файлов буду делать.

    А если после обрезки имени файла повторить get-childitem для поиска длинных имен файлов? Чтоб создать "обновленный" массив.

    Предлагаете в массиве создать новый массив? Ну во первых первый массив так и останется, будет выполняться, во вторых у меня большое хранилище, очень много файлов, будет занимать много времени. Я вроде на верном пути от того, что хочу, надо немного времени на тест.

    имхо, тут происходит изобретание велосипеда который уже существует
    Это совсем не то, что надо. Мне надо не просто сократить имя (для скрипта), а физически на хранилище уменьшить длину пути к файлу и сам файл. Чтобы он был не более 255 символов.

    4 апреля 2021 г. 4:13
  • Может тогда лучше создать "полноценную" утилиту с помощью VS, а не использовать PS? 

    Alexandr_Smirnoff

    4 апреля 2021 г. 9:38
  • а что вам мешает переименовать ваши длинные пути согласно шортформа описанного выше?

    UPD:

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


    The opinion expressed by me is not an official position of Microsoft

    4 апреля 2021 г. 10:02
    Модератор