Jak skopiować określone pliki (bez hierarchii folderów), ale nie nadpisać istniejących plików?
Muszę skopiować wszystkie pliki *.doc
(ale nie foldery, których nazwy pasują do *.doc
) z folderu sieciowego \\server\source
(w tym pliki we wszystkich zagnieżdżonych folderach) do folderu lokalnego C:\destination
bez zachowania hierarchii zagnieżdżonych folderów (tzn. wszystkie pliki powinny iść bezpośrednio do C:\destination
, A żadne zagnieżdżone foldery nie powinny być tworzone w C:\destination
). W przypadku, gdy istnieje kilka plików o tej samej nazwie z różnych podfolderów \\server\source
, tylko pierwszy z nich powinien być skopiowany i nigdy nie nadpisany - wszystkie sprzeczne pliki znalezione później powinny być pomijane (może być wiele takich przypadków, a pomijane pliki nie powinny być przesyłane przez sieć, w przeciwnym razie zajęłoby to zbyt dużo czasu). Oto moja próba zaimplementowania go w PowerShell:
cp \\server\source\* -Recurse -Include *.doc -Container:$false -Destination C:\destination
IstniejÄ… co najmniej dwa problemy z tÄ… komendÄ…:
- kopiuje foldery, których nazwy pasują
*.doc
. - W przypadku sprzecznych nazw każdy plik znaleziony później jest przesyłany przez Sieć i nadpisuje poprzedni jeden.
Czy możesz zasugerować, jak rozwiązać te problemy?
Wdrożenia z wykorzystaniem copy
, xcopy
, robocopy
, cscript
lub *.bat
, *.cmd
są również mile widziane.
Lokalny system operacyjny to Windows 8, a system plików to NTFS.
5 answers
Najpierw sporządziłbym listę plików i zatwierdził ją podczas przeglądania listy.
CoÅ› takiego:
$srcdir = "\\server\source\";
$destdir = "C:\destination\";
$files = (Get-ChildItem $SrcDir -recurse -filter *.doc | where-object {-not ($_.PSIsContainer)});
$files|foreach($_){
if (!([system.io.file]::Exists($destdir+$_.name))){
cp $_.Fullname ($destdir+$_.name)
};
}
Więc użyj Get-ChildItem
, Aby wyświetlić listę plików w folderze źródłowym pasujących do filtra, Przełącz where-object
, aby usunąć katalogi.
Następnie przejrzyj każdy plik w pętli foreach
i sprawdź, czy nazwa pliku (nie pełna) istnieje w miejscu docelowym, używając metody Exists
klasy system.io.file
. NET.
Jeśli nie, skopiuj, używając tylko oryginalnej nazwy pliku (upuszczając oryginał ścieżka).
Użyj opcji -whatif
na kopii podczas testowania, więc wyświetla tylko to, co zrobi, na wypadek, gdyby wynik nie był tym, czego chciałeś: -)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-23 12:01:00
Poprzednie odpowiedzi wydają mi się zbyt skomplikowane, chyba że coś źle zrozumiałem. Powinno działać:
Get-ChildItem "\\server\source\" *.doc -Recurse | ?{-not ($_.PSIsContainer -or (Test-Path "C:\Destination\$_"))} | Copy-Item -Destination "C:\Destination"
Żadne z wbudowanych poleceń-copy, xcopy lub robocopy-nie zrobi tego, co chcesz na własną rękę, ale istnieje narzędzie o nazwie xxcopy, które będzie, wygodnie dostępne na http://www.xxcopy.com . posiada wiele wbudowanych opcji specjalnie do spłaszczania drzew katalogów w jeden katalog. Następujące rzeczy zrobią to, co Ty opisany:
xxcopy "\\server\source\*.doc" "C:\Destination" /SGFO
Jednak xxcopy ma wiele innych opcji obsługi zduplikowanych nazw plików niż tylko kopiowanie pierwszej napotkanej, takich jak dodawanie nazwy katalogu źródłowego do nazwy pliku lub dodawanie sekwencyjnych identyfikatorów numerycznych do wszystkich oprócz pierwszej, lub wszystkich oprócz najnowszej lub najstarszej. Szczegóły na tej stronie: http://www.xxcopy.com/xxcopy16.htm
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-09 18:32:42
# Get all *.doc files under \\server\source
Get-ChildItem -Path \\server\source *.doc -Recurse |
# Filter out directores
Where-Object { -not $_.PsIsContainer } |
# Add property for destination
Add-Member ScriptProperty -Name Destination -Value { Join-Path 'C:\destination' $this.Name } -PassThru |
# Filter out files that exist on the destination
Where-Object { -not (Test-Path -Path $_.Destination -PathType Leaf } |
# Copy.
Copy-Item
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-09 08:04:31
Po co używać foreach, skoro masz już rurociąg? Obliczone właściwości na wygraną!
Get-ChildItem -Recurse -Path:\\Server\Path -filter:'*.doc' |
Where { -not $_.PSIsContainer } |
Group Name |
Select @{Name='Path'; Expression={$_.Group[0].FullName}},@{Name='Destination'; Expression={'C:\Destination\{0}' -f $_.Name}} |
Copy-Item
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-13 01:55:27
$docFiles = Get-ChildItem -Path "\\server\source" -Recurse | Where-Object {$_.Attributes.ToString() -notlike "*Directory*" -and ($_.Name -like "*.doc" -or $_.Name -like "*.doc?")} | Sort-Object -Unique;
$docFiles | ForEach-Object { Copy-Item -Path $_.fullname -Destination "C:\destination" };
Pierwsza linijka czyta każdy*.plik doc i *.doktorze? (rozważa więc również Office 2010 .format docx), z wyłączeniem katalogów i duplikatów plików.
Druga linia kopiuje każdy element z miejsca docelowego do źródła (folder C:\destination musi już istnieć).
Ogólnie proponuję podzielić polecenie na kilka linii, ponieważ łatwiej jest wyprodukować kod (w tym przypadku pierwsze zadanie: get files, drugie zadanie: copy files).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-09 10:03:54