Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Удалить файлы по спискам, содержащимся в нескольких *.lst (http://forum.oszone.net/showthread.php?t=338557)

dassen 05-01-2019 02:07 2849890

Удалить файлы по спискам, содержащимся в нескольких *.lst
 
В папке MainFldr (и во вложенных в нее подпапках) нужно удалить (лучше в корзину) файлы по спискам, содержащимся во всех *.lst из папки LstFldr.
Другими словами:
В папке LstFldr есть несколько десятков *.lst , каждый из которых содержит список файлов, подлежащих удалению (ФПУ) из папки MainFldr (и из вложенных в нее подпапок).
Других файлов в папке LstFldr нет.
В *.lst имена ФПУ представлены без адресов; по одному на строку (пустых и посторонних строк нет), могут повторяться в различных *.lst.
Все ФПУ только с цифрами и EN-буквами в именах, с расширениями.
ФПУ (и/или содежащие их папки) могут быть с атрибутами +H, +S, +R.
ФПУ могут повторяться в папке MainFldr (и во вложенных в нее подпапках).
Хотелось бы также вывести в файл Deleted.lst список удаленных файлов (с их полными адресами до удаления),
а в файл NonDeleted.lst вывести список ФПУ, которые так и не удалились (с их полными адресами).
(OS: WinXP SP3)

Iska 05-01-2019 03:01 2849900

Цитата:

Цитата dassen
есть несколько десятков *.lst , каждый из которых содержит список файлов »

Упакуйте несколько таких файлов в архив, каковой приложите к сообщению.

Цитата:

Цитата dassen
без адресов; »

В переводе на русский — без путей?

Цитата:

Цитата dassen
Хотелось бы также вывести в файл Deleted.lst список удаленных файлов (с их полными адресами до удаления), »

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

dassen 05-01-2019 04:24 2849902

Вложений: 1
смоделировал ситуацию как-то так

Iska 05-01-2019 07:50 2849907

На PowerShell это может выглядеть, например, так:
Скрытый текст
Код:

$sListFolder  = 'C:\Мои проекты\0235\SomethingLikeThis\LstFldr'
$sSourceFolder = 'C:\Мои проекты\0235\SomethingLikeThis\MainFldr'

if([System.IO.Directory]::Exists($sListFolder)) {
    if([System.IO.Directory]::Exists($sSourceFolder)) {
        $hFiles = @{}
       
        Get-ChildItem -Path $sListFolder -Filter '*.lst' -File |`
            ForEach-Object -Process {
                Write-Host "Reading file name(s) from [$($_.FullName)]…" -ForegroundColor Cyan

                Get-Content -Path $_.FullName |`
                    ForEach-Object -Process {
                        if(-not $hFiles.ContainsKey($_)) {
                            Write-Host "`tAdding unique file name [$_]" -ForegroundColor White
                            $hFiles.Add($_, $_)
                        } else {
                            Write-Host "`tDuplicate file name [$_] found, skipping" -ForegroundColor Gray
                        }
                    }
            }
        Write-Host "Total found $($hFiles.Count) unique file name(s).`r`n" -ForegroundColor Cyan

        if($hFiles.Count -gt 0) {
            Write-Host "Deleting file(s)…" -ForegroundColor Cyan

            Set-Content -Path "Deleted.lst"    -Encoding Default -Value '' -NoNewline
            Set-Content -Path "NonDeleted.lst" -Encoding Default -Value '' -NoNewline

            Get-ChildItem -Path $sSourceFolder -Include $($hFiles.Keys) -File -Recurse -Force |`
                ForEach-Object -Process {
                    $sFullFileName = $_.FullName

                    Write-Host "`t$sFullFileName" -ForegroundColor White
                   
                    try {
                        $_.Attributes = [System.IO.FileAttributes]::Normal
                        $_.Delete()
                        Add-Content -Path "Deleted.lst" -Encoding Default -Value $sFullFileName
                    } catch {
                        Write-Host "`t`tAn error occured while deleting file [$sFullFileName]" -ForegroundColor Red
                        Add-Content -Path "NonDeleted.lst" -Encoding Default -Value $sFullFileName
                    }
                }
        } else {
            Write-Host "Nothing to delete." -ForegroundColor Cyan
        }
    } else {
        Write-Host "Can't find source folder [$sSourceFolder]." -ForegroundColor Red
    } 
} else {
    Write-Host "Can't find list's folder [$sListFolder]." -ForegroundColor Red
}


Busla 05-01-2019 14:50 2849968

Iska, передать весь список искомых файлов через Include в Get-ChildItem - интересная идея - я её не думал - возьму на заметку. Спасибо.
P.S. ну и традиционное про лютый трэш и угар:
если вы раскрашиваете сообщения исходя из их разной ценности - используете стандартные Write-Debug, Write-Verbose, Write-Info - они и сами раскрасят, и ими можно извне хоть как-то управлять
но вообще, это бесполезное самолюбование - как в кино: по экрану бежит куча текста который никто не читает и в принципе не в состоянии прочитать и проанализировать. Лучше бы уж тогда Write-Progress впилили
заворачивать всё в глобальные if - ну так себе подход неудобно отслеживать к чему относится закрывающая скобка и else - разверните условие и сделайте выход сразу после if
.Net библиотеки не знают ничего про PSdisk, поэтому ваши скритпы невозможно тестировать стандартным Pester
метод файлового объекта Delete() вместо Remove-Item - тоже та ещё засада - я не могу в начале скрипта к примеру написать $PSDefaultParameterValues.Add("Remove-Item:WhatIf",$True) и посмотреть: что же происходит

YuS_2 05-01-2019 15:35 2849974

Цитата:

Цитата Iska
Код:

...
Get-ChildItem ... -File
...

»

OS WinXP SP3, выше PoSh v 2.0, увы не прыгнуть...

megaloman 05-01-2019 15:43 2849975

CMD тоже можно. Была проблема с атрибутами файлов.
Код:

@Echo Off
cls
        Set "BoxData=Z:\Box_In\SomethingLikeThis\MainFldr"
        Set "FileList=Z:\Box_In\SomethingLikeThis\LstFldr\*.lst"

        Set /A N=10000
        FOR %%f IN (%FileList%) DO FOR /F "usebackq delims=" %%s IN (`More "%%f"`) DO Call :Count "%%~nxs"
       
        If %N%==%Max% Echo !!! "%FileList%" not found &Exit /B 2

        Call :MyDel "%BoxData%"
        FOR /F "usebackq delims=" %%d IN (`2^>nul Dir "%BoxData%" /B /S /A:D`) DO Call :MyDel "%%d"
Pause
GoTo :Eof

:Count
        Set /A N+=1
        Set "@@%N%=%~1"
GoTo :Eof

:MyDel
        FOR /F "usebackq tokens=1* delims==" %%f IN (`Set "@@"`) DO If Exist "%~1\%%~g" (
                Attrib -R -H -S "%~1\%%~g"
                Del "%~1\%%~g"
        )
GoTo :Eof


Iska 05-01-2019 15:50 2849977

Цитата:

Цитата YuS_2
OS WinXP SP3, выше PoSh v 2.0, увы не прыгнуть... »

Угу. Там по-старому, через фильтр — Where-Object -FilterScript { -not $_.PSIsContainer }.

dassen 05-01-2019 19:55 2850031

megaloman, большое спасибо. То, что надо. Основную задачу батник выполняет.
Цитата:

Цитата megaloman
CMD тоже можно »

именно cmd и интересовало.

Iska 09-01-2019 06:03 2850726

Цитата:

Цитата Busla
передать весь список искомых файлов через Include в Get-ChildItem - интересная идея »

С тех пор, как Microsoft начал указывать типы параметров у командлетов — жить стало легче, жить стало веселей ;).

Цитата:

Цитата Busla
если вы раскрашиваете сообщения исходя из их разной ценности »

Нет, не поэтому. Просто группировка вывода, цветовая дифференциация штанов.

Цитата:

Цитата Busla
используете стандартные Write-Debug, Write-Verbose, Write-Info - они и сами раскрасят, и ими можно извне хоть как-то управлять »

Если бы это были Debug/Verbose/Info сообщения — тогда, да. В данном случае я не вижу нужды наделять простой вывод искусственным смыслом. Я понимаю Вашу мысль, но я вижу ровно два места вывода — stdout и stderr, и не стремлюсь здесь что-то менять. И, к тому же, мне нужно, чтобы пользователь, например, гарантированно видел сообщение о той или иной ошибке.

Цитата:

Цитата Busla
но вообще, это бесполезное самолюбование - как в кино: по экрану бежит куча текста который никто не читает и в принципе не в состоянии прочитать и проанализировать. »

У меня — не бежит. У меня — при нужде передаётся в редактор Far Manager'а:
Код:

edit:< powershell.exe -File "C:\Мои проекты\0235\0003.ps1"
Зачем тогда пользовать консоль, если не пользовать все её возможности?!

Цитата:

Цитата Busla
Лучше бы уж тогда Write-Progress впилили »

Для удаления нескольких сотен файлов? Не вижу особого смысла. Основной временно́́й расход здесь займёт поиск файлов — FindFirst()/FindNext(), а само удаление будет тупо в уже заполненный кэш писаться.

Цитата:

Цитата Busla
заворачивать всё в глобальные if - ну так себе подход неудобно отслеживать к чему относится закрывающая скобка и else - разверните условие и сделайте выход сразу после if »

Редактор вменяемый фолдинг не поддерживает, что ли? Я вот как раз наоборот, терпеть не могу кучу этих вечных выходов посерёд кода. Как по мне — так в моём подходе зараз виден весь алгоритм целиком и полностью. Впрочем, это кому как, соглашусь, что зависит сие от восприятия конкретного человека.

Цитата:

Цитата Busla
.Net библиотеки не знают ничего про PSdisk, поэтому ваши скритпы невозможно тестировать стандартным Pester
метод файлового объекта Delete() вместо Remove-Item - тоже та ещё засада - я не могу в начале скрипта к примеру написать $PSDefaultParameterValues.Add("Remove-Item:WhatIf",$True) и посмотреть: что же происходит »

Вы не поверите: чем теснее мне приходится общаться с командлетами, тем больше мне начинает нравиться прямое использование методов .Net — меньше шансов нарваться на какой-нибудь очередной затык в реализации командлета :).


Время: 19:20.

Время: 19:20.
© OSzone.net 2001-