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

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Найти файлы по маске и заменить в них строки (http://forum.oszone.net/showthread.php?t=335260)

hunk3r 09-06-2018 18:54 2817656

Найти файлы по маске и заменить в них строки
 
Всем привет.
Давно читаю форум и часто пользуюсь батниками, но ума не дам как дописать следующее:
Есть директория E:\Steam\userdata\ в ней множество др. директорий, в каждой из которых есть файл с именем sharedconfig.vdf

Мне необходимо в каждом найденном по имени "sharedconfig.vdf" файле заменить строку "cloudenabled" "1" на "cloudenabled" "0" (строка находится в рандомном месте как по вертикали файла, так и по горизонтали)
Начало простое:
Код:

For /F %%i in ('"where /R E:\Steam\userdata\ "sharedconfig.vdf""') do (
Прошу, помогите закончить скрипт.

megaloman 09-06-2018 19:05 2817658

hunk3r, Хотелось бы потрогать файл руками - упакуйте пожалуйста и предоставьте.

YuS_2 09-06-2018 19:56 2817664

Цитата:

Цитата hunk3r
Есть директория E:\Steam\userdata\ в ней множество др. директорий, в каждой из которых есть файл с именем sharedconfig.vdf
Мне необходимо в каждом найденном по имени "sharedconfig.vdf" файле заменить строку "cloudenabled" "1" на "cloudenabled" "0" (строка находится в рандомном месте как по вертикали файла, так и по горизонтали) »

В какой кодировке файлы?
powershell
script.ps1
Код:

dir "E:\Steam\userdata\" -rec -inc 'sharedconfig.vdf'|%{
    (gc $_.fullname -enc utf8 -raw) -replace '(?<=\"cloudenabled\"\s*\")1(?=\")','0'|`
    set-content $_.fullname -enc utf8
}

для запуска:
run.bat
Код:

@echo off
echo Выполняем...
powershell -ex bypass .\script.ps1
echo Готово.
pause


hunk3r 09-06-2018 20:01 2817665

Кодировка 1251 как я понял.

Iska 09-06-2018 20:06 2817668

Цитата:

Цитата YuS_2
В какой кодировке файлы? »

Потому и требуем упаковать в архив и приложить. И кроме кодировки, там ещё может быть существенной такая радость механика, как тип конца строки (в трёх ипостасях).


Цитата:

Цитата hunk3r
Кодировка 1251 как я понял. »

hunk3r, вот, чтобы Вам не гадать, а пишущим не заниматься ручным набором содержимого файла — делайте то, что просят: упакуйте файл в архив и приложите к сообщению.

YuS_2 09-06-2018 20:12 2817670

Цитата:

Цитата hunk3r
Кодировка 1251 как я понял. »

Так... вот выше правильно говорят - упакуйте и приложите, а там увидим :)
А пока, по Вашим данным, скрипт выше поправил...

Цитата:

Цитата Iska
как тип конца строки (в трёх ипостасях) »

в варианте на powershell, это не столь важно...

hunk3r 09-06-2018 20:18 2817672

Вложений: 1
Прошу прощения, торопился) Вот.

YuS_2 09-06-2018 20:27 2817674

Цитата:

Цитата hunk3r
торопился »

Спешить не надо :)
Кодировка там UTF8.
Вернул кодировку в скрипте...

hunk3r 09-06-2018 20:31 2817675

Цитата:

Цитата YuS_2
s* »

Спасибо!)
Если я правильно понимаю, то \s*\ между кавычками - это любое количество пробелов?

YuS_2 09-06-2018 20:34 2817676

Цитата:

Цитата hunk3r
это любое количество пробелов? »

это ноль или более пробельных символов, а не только пробелов...

hunk3r 09-06-2018 20:41 2817677

Проверил, работает. Еще раз всем спасибо!

Iska 09-06-2018 20:46 2817679

Цитата:

Цитата YuS_2
в варианте на powershell, это не столь важно... »

Как это — неважно? Что возвращает командлет Get-Content? Если я понимаю правильно — массив объектов, сформированных из строк, так? И что будет, например, с концами строк в формате Unix в результате простого банального Get-Content | Set-Content? Правильно — они превратятся в концы строк в формате DOS/Windows.

YuS_2 09-06-2018 20:52 2817682

Цитата:

Цитата Iska
И что будет, например, с концами строк в формате Unix »

Лучше один раз увидеть, чем сто раз услышать :)
В приложенном файле, как раз, конец строк в формате Unix...
Протестируйте вышеприведенный скрипт...

Цитата:

Цитата Iska
Правильно — они превратятся в концы строк в формате DOS/Windows. »

Это утверждение? Зачем тогда были вопросы? :)
Цитата:

Цитата Iska
Если я понимаю правильно — массив объектов, сформированных из строк, так? »

В данном случае, не так...

Iska 09-06-2018 21:07 2817687

Цитата:

Цитата YuS_2
Лучше один раз увидеть, чем сто раз услышать
В приложенном файле, как раз, конец строк в формате Unix...
Протестируйте вышеприведенный скрипт... »

YuS_2, приношу свои извинения, просмотрел параметр -raw.


Наблюдаю забавный побочный эффект — в файл добавляется пустая строка с концом строки в формате DOS/Windows.

И файл в оригинале был без BOM.

YuS_2 09-06-2018 21:32 2817693

Цитата:

Цитата Iska
Наблюдаю забавный побочный эффект — в файл добавляется пустая строка с концом строки в формате DOS/Windows.
И файл в оригинале был без BOM. »

Это да, есть такой момент...
Способ сохранения без bom есть, но если это некритично, то и смысла это делать особого нет...
Что касается лишней строки... ну, это ведь микрософт, с ним без веселья никак...
Можно, конечно, оттримить текст, лишней строки не будет, но конечным символом массива текста, все же будет \r\n, от этого избавиться непросто..

Iska 09-06-2018 21:45 2817694

Цитата:

Цитата YuS_2
Способ сохранения без bom есть, но если это некритично, то и смысла это делать особого нет... »

Зато так будет правильно. Знать бы ещё, что файл и в оригинале (а не тот, который был нам предоставлен) был без BOM ;).

YuS_2 09-06-2018 22:15 2817701

Цитата:

Цитата Iska
Зато так будет правильно »

Правильно - категория относительная... :)
Самый "простой" вариант :) : разворачиваем параллельно существующему - PoSh Core (они не мешают друг другу), вот в нем уже есть возможность UTF8NoBOM... т.е. этот же скрипт будет в нем работать, останется только исправить кодировку на нужную.
Ну, или по-старинке:
Код:

$utf8nobom = new-object system.text.utf8encoding($false)
dir "E:\Steam\userdata\" -rec -inc 'sharedconfig.vdf'|%{
    $arr = ((gc $_.fullname -enc utf8 -raw) -replace '(?<="cloudenabled"\s*")1(?=")','0').trim()
    [io.file]::writealllines($_.fullname, $arr, $utf8nobom)
}


Iska 10-06-2018 01:13 2817720

Цитата:

Цитата YuS_2
Ну, или по-старинке: »

Тогда уж целиком делать:
Код:

$UTF8Encoding = New-Object -TypeName 'System.Text.UTF8Encoding' -ArgumentList $false
$sContent = [System.IO.File]::ReadAllText('C:\Мои проекты\0163\sharedconfig.vdf', $UTF8Encoding) -replace '(?<="cloudenabled"\s*")1(?=")','0'
[System.IO.File]::WriteAllText('C:\Мои проекты\0163\sharedconfig2.vdf', $sContent, $UTF8Encoding)

и нет проблем ни с кодировкой, ни с концами строк.

Вот за то я PowerShell и не люблю: хоть уже и напоминает отожравшегося монстра, но кучу простых и естественных вещей по-прежнему не умеет нормально делать, и выясняется, что старые дедовские способы программирования всё ещё работают надёжнее.

YuS_2 10-06-2018 08:14 2817733

Цитата:

Цитата Iska
и нет проблем ни с кодировкой, ни с концами строк. »

Можно и так, только организовать ещё рекурсивный отбор файлов... для цельности решения :)
Код:

$utf8nobom = new-object system.text.utf8encoding($false)
dir "E:\Steam\userdata\" -rec -inc 'sharedconfig.vdf'|%{
    $arr = ([io.file]::readalltext($_.fullname, $utf8nobom)) -replace '(?<="cloudenabled"\s*")1(?=")','0'
    [io.file]::writealllines($_.fullname, $arr, $utf8nobom)
}

и конечный \r\n, всё равно, никуда не денется... ведь gc -raw, делает то же самое...
Цитата:

Цитата Iska
Вот за то я PowerShell и не люблю: хоть уже и напоминает отожравшегося монстра, но кучу простых и естественных вещей по-прежнему не умеет нормально делать »

Имхо, так вроде не шибко-то и монстр, а то, что умеет многое - это плюс большой, да и способов решения задач у него множество (не работает так - решаем по-другому), в общем, на любой вкус и привычку... в том числе и dotnet хорошо пережевывает...
Во всяком случае, это уже далеко не ограниченный cmd...
К тому же, сейчас это открытый проект, развивается себе постепенно...

Iska 10-06-2018 08:42 2817735

Монстр, монстр ;). Командлеты и так уже перегружены всяческими параметрами (и, что самое печальное, многочисленными умолчаниями) по самое нехочу, причём картина, зачастую, складывается удручающая. Поначалу куча вещей банально оставалась за бортом, добавляясь только после многочисленных пинков со стороны пользователей через одну-две версии, и то не сразу, и через пень-колоду. Одни и те же сущности в разных командлетах могли быть тупо реализованы отличным образом. Какая-нибудь никому не нужная хрень могла появиться ещё в первой версии, а такие банальные и необходимые для администрирования вещи, как отправка почты по защищённому протоколу, работа с архивами, работа с ftp, работа с альтернативными потоками данных, получали свои командлеты спустя долгое, долгое время.

Я бы лично предпочёл какой-нибудь интерпретатор для .Net по аналогу с WSH на основе той же сладкой парочки VB/JS.

YuS_2 10-06-2018 13:06 2817748

Цитата:

Цитата Iska
Командлеты и так уже перегружены всяческими параметрами (и, что самое печальное, многочисленными умолчаниями) по самое нехочу, причём картина, зачастую, складывается удручающая. »

Да что там удручающего? Параметры есть, иногда их много, но есть же справка, причем встроенная и с примерами...
Параметры есть в любом языке, но вот справка аналогичная к ним... где ещё есть такая же? Ну, я имею в виду wsh и cmd, для сравнения... а про функционал можно и не упоминать даже...
Кроме того, где есть ещё такая реализация конвейеров, причем с объектами вместе?

Цитата:

Цитата Iska
Я бы лично предпочёл какой-нибудь интерпретатор для .Net по аналогу с WSH на основе той же сладкой парочки VB/JS. »

Сколько людей, столько и мнений, как говорится :)
Если бы с WSH было бы всё так радужно, то никакой монад на свет и не появился бы...
Да и портянки кодов можно посравнивать при аналогичных задачах... powershell, явно выиграет.

pzh2393 07-06-2019 12:05 2874762

Добрый день!
Хотел адаптировать привелденный здесь скрипт для своих нужд, но что-то не получается..
Нужно во всех файлах Description поменять номер версии находящийся в теге <targetVersion>14.4.0</targetVersion>
Код:

dir "D:\WINDOWS\" -rec -inc 'Description'|%{
    (gc $_.fullname -enc utf8 -raw) -replace '(?<=\"<targetVersion>\"\s*\")14.4.0(?=\")','14.4.1'|`
    set-content $_.fullname -enc utf8
}

При запуске пишет ошибку "не удается найти параметр, соответствующий имени параметра "raw".
Прошу помочь с исправлением скрипта!

Нашел еще такой пример, но тоже не работает..
Код:

$sSourceFolder  = 'D:\WINDOWS'
$sSourceFileName = 'Description'

$sString4Found  = '14.4.0'
$sString4Replace = '14.4.1'

if(Test-Path -Path $sSourceFolder -PathType Container) {
    Get-ChildItem -Path $sSourceFolder -Filter $sSourceFileName -File -Recurse | ForEach-Object -Process {
        $sContent = Get-Content -Path $_.FullName -Encoding Oem

        if($sContent -icontains $sString4Found) {
            Write-Host $_.FullName
            $sContent.Replace($sString4Found, $sString4Replace) | Set-Content -Path $_.FullName -Encoding Oem
        }
    }
} else {
    Write-Host "Can't find source folder $sSourceFolder." -ForegroundColor Red
}

На этот раз пишет, что "не удается найти параметр, соответствующий имени параметра "File".

YuS_2 07-06-2019 13:03 2874766

Цитата:

Цитата pzh2393
При запуске пишет ошибку "не удается найти параметр, соответствующий имени параметра "raw". »

Цитата:

Цитата pzh2393
"не удается найти параметр, соответствующий имени параметра "File". »

Всё это следствие устаревшей версии powershell. Чтобы всё заработало, необходимо её обновить.

pzh2393 07-06-2019 13:10 2874767

Цитата:

Цитата YuS_2
Чтобы всё заработало, необходимо её обновить. »

А обновить ее не обновляя саму виндовс возможно?

Iska 07-06-2019 14:06 2874773

Возможно. У Вас какая версия ОС?

pzh2393 07-06-2019 15:15 2874780

Цитата:

Цитата Iska
какая версия ОС? »

Windows 7 x86

pzh2393 07-06-2019 16:14 2874785

Вроде установил более новую версию powershell (7.0.0-preview.1), при запуске теперь нет тех ошибок, но и замена все равно не происходит.

YuS_2 07-06-2019 17:59 2874796

Цитата:

Цитата pzh2393
но и замена все равно не происходит »

так это естественно, т.к. шаблон регвыра совсем не соответствует этому:
Цитата:

Цитата pzh2393
<targetVersion>14.4.0</targetVersion> »

- здесь нет кавычек. А внутри файлов они присутствуют? Если нет, то:
Код:

dir 'D:\WINDOWS' -rec -inc 'Description' |%{
    (gc $_.fullname -enc utf8 -raw) -replace '(?<=<targetVersion>\s*)14.4.0(?=\s*<)','14.4.1' |
    set-content $_.fullname -enc utf8
}


pzh2393 07-06-2019 18:38 2874800

YuS_2, благодарю, теперь работает.


Время: 07:10.

Время: 07:10.
© OSzone.net 2001-