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 между кавычками.
Сделаю все возможное для моего следующего вопроса, чтобы показать некоторые усилия. Независимо от того, оба ваших ответа помогли мне решить эту проблему.
Итак, еще раз большое спасибо!