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

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

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

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

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

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

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

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

3 ответа

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

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

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

Краткое объяснение: команда рекурсивно находит все прямые и косвенные подкаталоги d:\root названный 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

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

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

Все это, как говорится, если мое предположение верно. По сути, сделайте фильтр для папки покупок на любом диске на хосте, а затем 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

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

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

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

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

Другие вопросы по тегам