Я пишу сценарий автоматической оценки, который предупреждает пользователя, если учащийся выполнил/не выполнил требования к каталогу: в частности, один файл main.cpp
в папке с соответствующим именем. Если этот файл не найден на верхнем уровне, предупредите пользователя, но продолжайте рекурсивно искать файл в любом подкаталоге. Если файл не найден, отправить сообщение об ошибке, но продолжить обработку остальных каталогов в родительском каталоге.
Пока это моя попытка, и она не совсем работает — предупреждение отправляется даже тогда, когда у пользователя вообще нет файла main.cpp
, когда мне нужны только 3 возможных выхода:
Как я могу это исправить?
function Copy-Files {
param (
[Parameter(Mandatory)][string]$CurrentDir,
[Parameter(Mandatory)][string]$StudentNum
)
# Try to copy assignment files to the marking folder. Check error conditions and warn marker appropriately.
try {
$DoneFiles | ForEach-Object {
Copy-Item -Force -Path "$CurrentDir\$_" -Destination .\marking -ErrorAction Stop
}
}
catch {
try {
$DoneFiles | ForEach-Object {
Get-ChildItem -Path $CurrentDir -File -Recurse -Filter "$_" | Copy-Item -Force -Destination .\marking -ErrorAction Stop
}
Write-Warning "$StudentNumber did not follow the specified folder convention, but all files were submitted."
}
catch {
Write-Error -Message "$StudentNumber did not submit any of: $DoneFiles." -Category InvalidData
Read-Host -Prompt "Press Enter to continue"
}
}
}
Get-ChildItem -Directory -Filter "*_lab${Env:AssignNumber}" | ForEach-Object {
$CurrentFolder = $_
$StudentNumber = $CurrentFolder.Name.Replace("_lab${Env:AssignNumber}", "")
Copy-Files -CurrentDir $CurrentFolder -StudentNum $StudentNumber
if ($AllFound -and $IsCMake) {
Invoke-CMake -DoneFileNames $DoneFiles -IsFirstCompile $FirstCompile -StudentNum $StudentNumber
}
# Run VS Code with diff
Compare-Code -DoneFileNames $DoneFiles -StudentNum $StudentNumber
}
Проблема заключается в неудобном поведении Copy-Item
. Если вы передаете пустую/нулевую коллекцию через конвейер (как в Get-ChildItem
), он не выдает ошибку. Это отличается от того, что вы ожидаете, поскольку конвейер в $null
выдает ошибку:
Get-ChildItem './MySrc' -Filter 'BadFilter' | Copy-Item ./MyDst ## No Error
$Null | Copy-Item ./MyDst ## Does Error
Для файлов я предпочитаю структуру типа If (Test-Path){}
, а не Try
/Catch
, чтобы убедиться, что пути и тому подобное все еще действительны, прежде чем пытаться внести изменения:
# Check if file exists in correct path and copy,
If (Test-Path "$CurrentDir\$_") {
Copy-Item -Force -Path "$CurrentDir\$_" -Destination .\marking
}
# Otherwise check recursively for the correct file and show a warning if found
ElseIf (Get-ChildItem -Path $CurrentDir -File -Recurse -Filter "$_") {
Write-Warning "$StudentNumber did not follow the specified folder convention, but all files were submitted."
Get-ChildItem -Path $CurrentDir -File -Recurse -Filter "$_" |
Copy-Item -Force -Destination .\marking
}
# Error out if file not found
Else {
Write-Error -Message "$StudentNumber did not submit any of: $DoneFiles." -Category InvalidData
Read-Host -Prompt "Press Enter to continue"
}