PowerShell: переименование / удаление файлов в папке, которая может появляться в разных местах иерархии файлов

330
loewie1984

В настоящее время пытаются выяснить способ переименования файлов PDF в определенной папке ( /root), которые прямо или косвенно находятся внутриpurchases папки, которая сама прямо или косвенно находится внутри /rootпапки. Я хотел бы добиться этого с помощью PowerShell, но не могу достичь чего-то большего, чем примеры, которые я нашел по многочисленным темам.

Например, с этой структурой каталогов:

/root/<subfolder1>/purchases/invoice1.pdf /root/<subfolder1>/order.pdf /root/<subfolder2>/purchases/invoice2.pdf 

Предполагается переименовывать или удалять только те файлы PDF, которые находятся в папках «покупок». Файлы PDF в любой другой папке нельзя трогать.

<subfolderX> имена неизвестны (то есть они могут быть все что угодно, например, «а» или «б»).

Скрипт должен рекурсивно запускать все папки.

Любое руководство по достижению этого будет оценено.

1
вместо двух вызовов `gci`, как предлагают другие ответы, вы можете просто сделать это:` gci C: \ Root * .pdf -Recurse | ? DirectoryName -imatch 'покупка'`, при этом будут возвращены только те файлы PDF, у которых в названии каталога (пути) есть строка «покупка». SimonS 5 лет назад 1
Вы правы @SimonS! Можно использовать `gci -Recurse \ root \ *. Pdf | ? {$ _. DirectoryName -imatch '. * \\ покупок (\\. * | $)'} | % FullName` вместо моего ответа, но это не обязательно быстрее (в зависимости от точной файловой структуры), потому что он не использует возможности фильтрации PowerShell FileSystem Provider (то есть эффективную поддержку для подстановки). Youssef Abidi 5 лет назад 0

3 ответа на вопрос

2
Youssef Abidi

Короткий ответ

Чтобы отобразить имена файлов PDF, прямо или косвенно содержащихся в прямом или косвенном подкаталоге d:\rootnamed purchases, вы можете использовать:

gci -Directory -Recurse d:\root\purchases | % { gci -Recurse "$_\*.pdf" } | % FullName 

Краткое объяснение: команда рекурсивно находит все прямые и косвенные подкаталоги d:\rootnamed purchases, затем рекурсивно находит все файлы PDF в каждом из этих подкаталогов, а затем возвращает полный путь каждого из этих файлов PDF.

Другие варианты использования

Чтобы удалить эти файлы PDF:

gci -Directory -Recurse d:\root\purchases | % { gci -Recurse "$_\*.pdf" } | ri 

Чтобы переименовать эти PDF-файлы (например, добавив префикс и суффикс к базовому имени):

gci -Directory -Recurse d:\root\purchases | % { gci -Recurse "$_\*.pdf" } | % { rni $_ "pref-$($_.BaseName)-suff.pdf" } 

Чтобы удалить purchasesкаталоги вместе со всем их содержимым:

gci -Directory -Recurse d:\root\purchases | ri -Recurse 

Детальное объяснение

  • gciпсевдоним для Get-ChildItem .
  • gci -Directory -Recurse d:\root\purchasesвозвращает все каталоги ( -Directory), чьи имена purchasesявляются прямыми или косвенными ( -Recurse) вложенными папками d:\root\. Другими словами, он вернется d:\root\purchases(если он существует) так же, как d:\root\b\c\purchasesи d:\root\a\purchases. Это не очень интуитивно понятно и, по-видимому, не объясняется в документации, но это текущее поведение (в PowerShell 6).
  • %является псевдонимом для ForEach-Object . Он выполняет блок скрипта (заключенный в фигурные скобки ( {}) для каждого объекта в конвейере).
  • gci -Recurse "$_\*.pdf"извлекает список файлов PDF, которые (прямо или косвенно) содержатся в ранее найденных purchasesкаталогах.
  • % FullName просто используется для отображения пути этих файлов PDF.
  • riявляется псевдонимом для Remove-Item . Он удаляет ранее вычисленный список файлов PDF (поскольку -Pathпараметр Remove-Itemкоманды принимает входные данные конвейера).
  • ri -Recurseпозволяет удалить ранее вычисленный список purchasesкаталогов вместе с их содержимым.
  • rni $_ "pref-$($_.BaseName)-suff.pdf"добавляет префикс ( pref-) и суффикс ( -suff) к базовому имени $_.BaseNameтекущего файла в конвейере (т. е. каждого из файлов PDF, которые мы ищем). Базовое имя файла - это имя файла без его расширения и rniпсевдоним для Rename-Item .

Тестирование этого решения (онлайн или локально)

Самое простое - попробовать это решение онлайн .

В противном случае вы можете создать образец структуры каталогов в testпапке текущего рабочего каталога со следующим фрагментом ( будьте осторожны : измените .\testна что-то другое, если у вас уже есть testпапка в текущем каталоге):

mkdir -ErrorAction SilentlyContinue .\test\a\purchases, .\test\a\e\, .\test\b\c\purchases\ Out-File .\test\a\purchases\invoice1.pdf Out-File .\test\a\order1.pdf Out-File .\test\a\e\order2.pdf Out-File .\test\b\c\purchases\invoice2.pdf Out-File .\test\b\c\purchases\invoice3.pdf 

Чтобы просмотреть все файлы в этой структуре каталогов, вы можете использовать:

gci -Recurse -File .\test | % FullName

Что бы вернуть что-то вроде:

D:\test\a\order1.pdf D:\test\a\e\order2.pdf D:\test\a\purchases\prefix-invoice1-suffix.pdf D:\test\b\c\purchases\prefix-invoice2-suffix.pdf D:\test\b\c\purchases\prefix-invoice3-suffix.pdf 

(Где D:заменяется вашим текущим рабочим каталогом.)

Выполнение команды, предоставленной в качестве ответа ( gci -Directory -Recurse .\test\purchases | % { gci -Recurse "$_\*.pdf" } | % FullName), отобразит файлы, которые необходимо удалить или удалить:

D:\test\a\purchases\invoice1.pdf D:\test\b\c\purchases\invoice2.pdf D:\test\b\c\purchases\invoice3.pdf 

Чтобы очистить после вашего теста:

rm -Recurse .\test 
1
postanote

Юсеф Абиди дал вам ответ, нацеленный на один диск, но кажется, что вы говорите, путь к папке. \ Покупки, неизвестно?

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

Все это, как говорится, если мое предположение верно. По сути, сделайте фильтр для папки покупок на любом диске на хосте, а затем PDF в этой папке и сделайте, как вы хотите.

Это на самом деле просто однострочная конвейерная команда - если вышеприведенное является верным предположением

(Get-PSDrive).Root -like '*:\' |  % { (Get-ChildItem -Path ((Get-ChildItem -Path $_ -recurse -Filter Purchases -Directory -ErrorAction SilentlyContinue).FullName) -Filter '*.pdf' -Verbose).FullName }  # Results  C:\purchases\powershell-cheat-sheet.pdf C:\purchases\PSPunctuationWallChart_1_0_4.pdf D:\Temp\purchases\powershell-cheat-sheet.pdf D:\Temp\purchases\PSPunctuationWallChart_1_0_4.pdf 

Конечно, вы можете разбить эту строку на что-то другое.

0
loewie1984

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

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

Итак, еще раз большое спасибо!

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

Похожие вопросы