Как изменить атрибут чтения списка файлов? - PullRequest
3 голосов
/ 04 октября 2009

Я новичок 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 ]

8 голосов
/ 04 октября 2009

Краткий ответ:

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 с. Они передаются в 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 при использовании в качестве логического значения. Но я думаю, что здесь достаточно сокращения.

2 голосов
/ 04 октября 2009

У Йоханнеса есть теория о проблеме, с которой вы сталкиваетесь. Я просто хотел отметить, что если вы используете PowerShell Community Extensions , вы можете выполнить это с помощью команд Set-Writable и Set-ReadOnly, которые поддерживают конвейер, например ::100100

Get-Content "c:\temp\test.txt" | Set-Writable

или краткая, псевдоним:

gc "c:\temp\test.txt" | swr

Псевдоним для Set-ReadOnly is sro. Я использую эти команды еженедельно, если не ежедневно.

...