Как изменить атрибут чтения для списка файлов?
Я новичок PowerShell. Я использовал пример скрипта и сделал замену из get-item на get-content в первой строке. Модифицированный скрипт выглядит следующим образом:
$file = get-content "c:\temp\test.txt"
if ($file.IsReadOnly -eq $true)
{
$file.IsReadOnly = $false
}
По сути, я пытаюсь выполнить действия, содержащиеся в test.txt, которые хранятся как пути UNC.
\\testserver\testshare\doc1.doc
\\testserver2\testshare2\doc2.doc
При запуске скрипта об ошибках не сообщается и никакие действия не выполняются даже при первой записи.
2 ответа
Короткий ответ:
sp (gc test.txt) IsReadOnly $false
Длинный ответ ниже
Ну, некоторые вещи не так с этим.
$file
на самом деле string[]
, содержащий строки вашего файла. Итак IsReadOnly
собственность относится к string[]
а не к фактическим файлам, представленным теми строками, которые оказываются именами файлов.
Итак, если я правильно вас понимаю, вы пытаетесь прочитать файл, содержащий другие имена файлов, по одному в каждой строке. И очистите атрибут "только для чтения" в этих файлах.
Начиная с Get-Content
здесь не так. Нам определенно понадобится это:
$filenames = Get-Content test.txt
Теперь у нас есть список имен файлов. Чтобы получить доступ к атрибутам файла, нам нужно либо преобразовать эти имена файлов в реальные FileInfo
объекты и оперируют на тех. Или мы передаем имена файлов -Path
аргумент Set-ItemProperty
,
Сначала я выберу первый подход, а затем перейду к другому. Таким образом, у нас есть куча имен файлов и хотим FileInfo
объекты от них. Это можно сделать с помощью foreach
цикл (так как нам нужно сделать это для каждого файла в списке):
$files = (foreach ($name in $filenames) { Get-Item $name })
Затем вы можете перебрать имена файлов и установить IsReadOnly
собственность на каждого из них:
foreach ($file in $files) {
$file.IsReadOnly = $false
}
Это был длинный и громоздкий вариант. Но тот, который, вероятно, больше всего подходит людям, не имеющим опыта работы с PowerShell. Вы можете уменьшить потребность в наличии нескольких коллекций вещей, используя конвейер. Конвейер переносит объекты из одного командлета в другой, и эти объекты по-прежнему имеют типы.
Итак, написав
Get-Content test.txt | Get-Item | ForEach-Object { $_.IsReadOnly = $false }
мы достигаем точно такого же результата. Мы читаем содержимое файла, получая кучу string
s. Те переданы Get-Item
который знает, что делать с конвейерным вводом: он обрабатывает эти объекты как пути к файлам; именно то, что нам нужно здесь. Get-Item
затем отправляет FileInfo
объекты далее по конвейеру, после чего мы зацикливаемся на них и устанавливаем свойство только для чтения в false
,
Теперь это было короче и, с небольшой практикой, может быть, даже проще. Но это все еще далеко от идеала. Как я уже говорил, мы можем использовать Set-ItemProperty
установить свойство "только для чтения" для файлов. И мы можем воспользоваться тем, что Set-ItemProperty
может принять массив строк в качестве входных данных для его -Path
параметр.
$files = Get-Content test.txt
Set-ItemProperty -Path $files -Name IsReadOnly -Value $false
Мы используем временную переменную здесь, так как Set-ItemProperty
не будет принимать входящие строки в качестве значений для -Path
непосредственно. Но мы можем встроить эту временную переменную:
Set-ItemProperty -Path (Get-Content test.txt) -Name IsReadOnly -Value $false
Скобки вокруг Get-Content
вызов необходим для того, чтобы сообщить PowerShell, что это единственный аргумент, и его следует сначала оценить.
Затем мы можем воспользоваться тем фактом, что каждый из этих параметров используется в позиции, где Set-ItemProperty
ожидает, что это так, поэтому мы можем опустить имена параметров и придерживаться только значений:
Set-ItemProperty (Get-Content test.txt) IsReadOnly $false
И затем мы можем сократить имена командлетов до их псевдонимов по умолчанию:
sp (gc test.txt) IsReadOnly $false
Мы могли бы на самом деле написать $false
как 0
чтобы сэкономить еще больше места, так как 0
преобразуется в $false
когда используется как логическое значение. Но я думаю, что здесь достаточно сокращения.
У Йоханнеса есть понимание теории проблемы, с которой вы сталкиваетесь. Я просто хотел отметить, что если вы используете расширения сообщества PowerShell, вы можете выполнить это с помощью команд Set-Writable и Set-ReadOnly, которые поддерживают конвейер, например:
Get-Content "c:\temp\test.txt" | Set-Writable
или краткая псевдоним:
gc "c:\temp\test.txt" | swr
Псевдоним для Set-ReadOnly является sro. Я использую эти команды еженедельно, если не ежедневно.