2014-04-21 10 views
7

Potrzebuję dodać siatkę bezpieczeństwa w moim skrypcie. Próbuję wykonać zadanie kopiowania na podstawie listy użytkowników dostarczonych przez plik tekstowy. Skopiuj pliki z katalogu domowego tego użytkownika do nowej lokalizacji. Po skopiowaniu plików sprawdź, czy plik istnieje w nowej lokalizacji. Jeśli tak, to usuń element.Powershell Plik IF pozycji już istnieje po skopiowaniu pozycji

Czy ktoś może mi pomóc? Po prostu nie wiem, jak zaimplementować logikę "if file exists".

$username = Get-Content '.\users.txt' 
foreach ($un in $username) 
{ 
    $dest = "\\server\homedirs\$un\redirectedfolders" 
    $source = "\\server\homedirs\$un" 
    New-Item -ItemType Directory -Path $dest\documents, $dest\desktop 

    Get-ChildItem $source\documents -Recurse -Exclude '*.msg' | Copy-Item -Destination $dest\documents 
    Get-ChildItem $source\desktop -Recurse -Exclude '*.msg' | Copy-Item -Destination $dest\desktop 

    Get-ChildItem $source\mydocuments, $source\desktop -Recurse -Exclude '*.msg' | Remove-Item -Recurse 
} 

Odpowiedz

5

Aby odpowiedzieć na to pytanie per se, można zrobić to tak:

Get-ChildItem $source\mydocuments, $source\desktop -Recurse -Exclude '*.msg' | %{ 
    if (Test-Path ($_. -replace "^$([regex]::escape($source))","$dest")) { 
    Remove-Item $_ -Recurse 
    } 
} 
  • Ścieżka testowa zwraca $ true, jeśli plik o podanej ścieżce istnieje, w przeciwnym razie: $ false.
  • $_ -replace "^$([regex]::escape($source))","$dest" przekształca ścieżkę każdego elementu źródłowego jesteś wymieniającym z odpowiednim ścieżce docelowej, zastępując $ źródło na początku ścieżki z $ dest.
  • Podstawowym regex na pierwszy argument operatora -Wymień jest ^$source (co oznacza „dopasuj wartość źródłowego $ na początku napisu”). Jednak musisz użyć [regex] :: escape w przypadku $ źródło zawiera dowolne znaki specjalne regex, które w rzeczywistości są wyjątkowo prawdopodobnie ze ścieżkami Windows, ponieważ zawierają odwrotne ukośniki. Na przykład wartość podana tutaj dla $ source zawiera \s, która w wyrażeniu regularnym oznacza "dowolny znak odstępu". $([regex]::escape($source)) interpoluje wartość $ źródło z dowolnymi znakami specjalnymi wyrażenia regularnego, tak, że pasujesz do wartości jawnej.

To powiedziawszy, jeśli Twoim celem jest skopiowanie każdego przedmiotu do nowej lokalizacji i usunięcie oryginału tylko wtedy, gdy kopia do nowej lokalizacji zakończy się powodzeniem, wydaje się, że wymyślasz nowe koło. Dlaczego po prostu nie używać Move-Item zamiast Copy-Item?


niezwiązanych bezpośrednio do pytania, ale zamiast powtarzać to samo polecenie dla każdego podkatalogu, można użyć foreach pętlę:

foreach ($subdir in (echo documents desktop)) { 
    # Whatever command you end up using to copy or move the items, 
    # using "$source\$subdir" and "$dest\$subdir" as the paths 
} 
+0

Dziękuję. Wciąż jestem początkującym programistą i PowerShell. To było bardzo pouczające. – Refried04

10

najkrótsza droga, aby usunąć plik, jeśli nie robi „t istnieje NIE jest użycie Test-Path ale:

rm my_file.zip -ea ig

jest Krótka wersja

rm my_file.zip -ErrorAction Ignore

który jest znacznie bardziej czytelne i bardziej DRY następnie

if (Test-Path my_file.zip) { rm my_file.zip }

+2

Jest to nie tylko bardziej czytelne, ale także bardziej poprawne. Wzór testowania istnienia jako pierwszy jest zły, ponieważ do czasu 'Test-Path' zwraca odpowiedź pozytywną, folder mógł już zostać usunięty, w którym to momencie wywołanie wanilii' Remove-Item' spowoduje błąd. –

+1

Nie byłem nawet tego świadomy i masz całkowitą rację. Dodatkową korzyścią jest to, że wyraźnie określa również zamiar programisty - jeśli chcę usunąć, testowanie czegoś wcześniej jest hałasem. – majkinetor

+0

W drugiej chwili problemem jest to, że może ukryć inny błąd. Na przykład plik może tam być, ale problem z uprawnieniami uniemożliwia jego usunięcie. Nie jestem ekspertem od PS, ale szybkie wyszukiwanie powoduje pojawienie się "ErrorVariable", która może okazać się przydatna w rozróżnianiu takich przypadków. –