cmd для удаления файлов, когда name отсутствует в списке, но только если в их папке нет строки в имени - PullRequest
1 голос
/ 12 июня 2019

Я не знаю много о cmd, но у меня есть папка X с большим количеством подпапок, и мне нужно создать cmd для удаления всех файлов в этих подпапках, но только:
- когда имя файла нетаким образом (list.txt - я поместил его в папку X, но я могу переместить его)
AND
- папка, содержащая этот файл, НЕ имеет строки (2019)в его имени.

В файле list.txt у меня есть все пути к папке с файлами (так что-то вроде X/folder1/folder2/filename.jpg).Удаляемые файлы - это не только .jpg.

Оглядываясь вокруг, я пробовал:

@echo off

setlocal enableextensions
set "folder=C:\X"
set "excludeFile=C:\X\list.txt"

for /d %%a in ("%folder%\*") do (
for /f "eol=: delims=" %%F in ('dir /b /a-d "%folder%" ^| findstr /vibg:"%excludeFile%"') do del "%folder%\%%F"
)

, но это не работает (и я не знаю, как сказатьисключить папки с 2019 в названии).
Кто-нибудь может помочь?

Это то, что в list.txt:

1.pdf
2.jpg
3.jpg
4.jpg
5.pdf

Ответы [ 3 ]

1 голос
/ 13 июня 2019
@echo off
setlocal enableextensions
set "folder=C:\X"
set "excludeFile=C:\X\list.txt"

for /d %%a in ("%folder%\*") do (
    for %%b in ("%%a\*") do (
        findstr /lx "%%~nxb" "%excludefile%" >nul || ECHO del "%%b"
    )
)

Цикл for /d %%a обрабатывает каждую папку (глубина = 1, не рекурсивная).
for %%b обрабатывает каждый файл (%%a\*) в этой папке.
findstr выглядит, еслиимя файла и расширение (%%~nxb) находятся в исключающем файле (/l = литерал, /x = "вся строка" и, если нет (||), файл удаляется.

ПРИМЕЧАНИЕ: Удалите ECHO, чтобы фактически включить команду del после устранения неполадок (если вы уверены, что она делает именно то, что вам нужно)

1 голос
/ 12 июня 2019

Вы можете фильтровать имена папок точно так же, как вы делаете для файлов, а именно, используя findstr или find.

Кроме того, я рекомендуюперейти в текущий обрабатываемый каталог для каждой итерации цикла (используя pushd / popd), поскольку dir /B возвращает только чистые имена файлов,чтобы вы могли легко работать не в той папке.

Вот как я мог бы закодировать это:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "folder=C:\X"
set "excludeFile=C:\X\list.txt"
set "excludeName=2019"
rem // Change to the root directory:
pushd "%folder%" && (
    rem // Loop through all directories but exclude those with certain partial names:
    for /F "delims= eol=|" %%D in ('dir /B /A:D "*" ^| find /V /I "%excludeName%"') do (
        rem // Change into currently iterated directory:
        pushd "%%D" && (
            rem // Loop through all files but exclude those listed in the list file:
            for /F "delims= eol=|" %%F in ('
                dir /B /A:-D "*.*" ^| findstr /V /L /I /X /G:"%excludeFile%"
            ') do (
                rem // Actually delete a file (remove `/P` after testing!):
                del /P "%%F"
            )
            rem // Return from currently iterated directory to root directory:
            popd
        )
    )
    rem // Return to original working directory:
    popd
)
endlocal

Возможно, вы заметили измененные параметры findstr: я добавил /Lфорсировать буквальные поиски;затем я заменил /B на /X, чтобы он соответствовал полным именам файлов (а не только началу).

Вы можете удалить параметр /P (подтверждение для каждого файла) из del и добавление /F (принудительное удаление файлов только для чтения) и опции /A (для удаления также скрытых файлов).


Основная проблема в вашем кодеявляется то, что вы никогда не используете for переменная %%a;во внутреннем цикле необходимо заменить каждое вхождение %folder% на %%~a.

0 голосов
/ 13 июня 2019

Один из способов сделать это - использовать скрипт PowerShell.Это работает на текущей PowerShell 5+.Это может быть сделано с более старыми версиями PowerShell с изменениями.Измените значение $ BaseDir на каталог 'X'.

Когда вы убедитесь, что правильные файлы будут удалены, удалите -WhatIf из командлета Remove-Item.

=== Remove-CustomFiles.ps1

$BaseDir = "C:\src\t"
$ExcludeDirs = @('*2019*')    # add directory names to exclude here
$PreciousNamesFile = Join-Path -Path $BaseDir -ChildPath 'list.txt'
$PreciousNames = Get-Content -Path $PreciousNamesFile

Get-ChildItem -Directory -Path $BaseDir -Exclude $ExcludeDirs |
    ForEach-Object {
        Get-ChildItem -File -Path $_.FullName |
            ForEach-Object {
                if ($PreciousNames -notcontains $_.Name) {
                    Remove-Item -Path $_.FullName -WhatIf
                }
            }
    }

Вызовите его в командной строке или в сценарии файла .bat, используя:

powershell -NoLogo -NoProfile -File "Remove-CustomFiles.ps1"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...