Показать полную графическую версию : [решено] Перенос файлов старше N дней
Доброго времени суток!
Накидал скрипт из пары строк, который должен пройтись по папки и если к файлу последний раз обращались больше чем N дней, он переносится в др папку, но скрипт не работает не поминая почему... Если указывать сравнение "ge", то он начинает всё(!) переносить, если "le" (по идее то что мне и надо), вообще ничего не происходит. Подскажите пожалуйста в чём ошибся?
cls
$path = "D:\other\test1"
$dest = "D:\other\test"
Get-ChildItem $path | where { $_.LastAccessTime -le ((Get-Date).AddDays(-5)) } | Move-Item -Destination $dest
Заранее спасибо!
А вывод, что показывает?
Get-ChildItem $path | Format-Table lastaccess*,name -Auto
И за одно посмотреть, не отключено ли обновление данного атрибута(вроде начиная с Vista отключено по умолчанию):
fsutil behavior query DisableLastAccess
Вывод Вашей команды:
LastAccessTime LastAccessTimeUtc Name
-------------- ----------------- ----
15.08.2014 10:09:57 15.08.2014 6:09:57 12
14.08.2014 15:54:00 14.08.2014 11:54:00 Презентации конференции
14.08.2014 15:54:00 14.08.2014 11:54:00 фото для печати
Большое спасибо! Нашёл косяк. Проблема в том, что Get-ChildItem $path без ключа -recurse смотрит на дату папки, а т.к. корневая папка имеет актуальную дату он её и пропускает, не смотря внутрь, где лежат старые файлы и папки. Но если поставить этот ключ, то он не сохранит структуру папок и просто все файлы старше N дней переместит в $dest.
Подскажите пожалуйста как это побороть?
Move-Item -Destination {md $_.DirectoryName.Replace("$path","$dest") -force}
Большое спасибо!!
Как раз то что надо.
Можете подсказать, у сего действия имеется какой-то ограниченный уровень вложенности? Сейчас попробовал, и получил не мало подобных ошибок:
WhatIf: Выполнение операции "Перемещение файла" над целевым объектом "Элемент: D:\pablic\Obmen\Foto\#Work\S\02 2014\222.rar Назначение: D:\Foto\#Work\S\02 2014\222.rar".
Move-Item : Ошибка при вводе данных в блок сценария для параметра "Destination". Невозможно вызвать метод для выражения со значением NULL.
строка:6 знак:116
+ ... m -Destination {md $_.DirectoryName.Replace("$path","$dest") -force} -WhatIf
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (мотивация марта Иркутск:PSObject) [Move-Item], ParameterBindingException
+ FullyQualifiedErrorId : ScriptBlockArgumentInvocationFailed,Microsoft.PowerShell.Commands.MoveItemCommand
WhatIf: Выполнение операции "Перемещение файла" над целевым объектом "Элемент: D:\pablic\Obmen\Foto\#Work\S\03 2014\111.rar Назначение: D:\Foto\#Work\S\03 2014\111rar".
Как я понял в данном примере, он споткнулся об папку D:\pablic\Obmen\Foto\#Work\S\03 2014\viv содержащая ещё вложенные папки и файлы.
Да, он выдает ошибки на папки, поэтому исключите их.
where { $_.LastAccessTime -le ((Get-Date).AddDays(-5)) -and !$_.PsIsContainer}
Да, он выдает ошибки на папки, поэтому исключите их. »
А что будет после исключения? Он оставит эту папку на месте?
Просто мне надо перенести всё что старше N дней из папки в папку.
Будут только файлы, сам объект папки будет исключен, т.е файлы расположенные в этой будут попадать под перемещение.
Извините за назойливость, просто хочется окончательно разобраться.
Получается что благодаря этой конструкции: Move-Item -Destination {md $_.DirectoryName.Replace("$path","$dest") -force} все файлы будут переносится с автоматическим сохранением и созданием структуры папок в папке назначения. И данная конструкция не умеет переносить папки, по этому мы их исключаем из переноса?
Я правильно понял?
Немного не так.
Для исключения папок мы используем атрибут PsIsContainer.
PS > dir
Каталог: C:\1
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 15.08.2014 11:36 1
d---- 15.08.2014 11:36 2
d---- 15.08.2014 11:36 3
-a--- 15.08.2014 11:36 8 1.txt
Только папки:
PS C:\1> dir | Where {$_.PsIsContainer}
Каталог: C:\1
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 15.08.2014 11:36 1
d---- 15.08.2014 11:36 2
d---- 15.08.2014 11:36 3
Только файлы:
PS C:\1> dir | Where {!$_.PsIsContainer}
Каталог: C:\1
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 15.08.2014 11:36 8 1.txt
DirectoryName - свойство только у файлов, у папок отсутствует. В данном случае конструкция не перемещает папки, а так можно и папки перемещать. Будут перемещаться, но без сохранения в исходном расположении, для этого есть Copy-Item.
Можно переносить и папки, но для случая когда у папки LastAccessTime подходит под условие, а все файлы внутри свежие, что у Вас предусмотрено?
Честно говоря затрудняюсь ответит...
Просто есть папка гигов в 200, в которой огромная количество папок и файлов в жуткой структуре подпапок.
Мне надо найти ВСЁ что старше N дней\месяцев и перенести оттуда в другую папку с сохранением структуры папок. Т.е. если кому-нибудь понадобится получить файл за 2010 год из этого ужаса, то можно узнать путь где он лежал и вытащить его из папки куда он был перемещён ($dest) по такому же пути (ну понятное дело что сменится корневая папка или диску куда это всё перенесется, но смысл я думаю поняте)
Ещё вариантов решения проблемы никто не подскажет?
Задачу решил следующими костылями:
скрипт 1 - перенос всех файлов старше N дней:
$days = 120
$path = "D:\data"
$dest = "D:\temp"
Get-ChildItem $path -Recurse | where { $_.LastAccessTime -le ((Get-Date).AddDays(-120)) -and !$_.PsIsContainer } | Move-Item -Destination { md $_.DirectoryName.Replace("$path","$dest") -force }После переноса файлов, структура каталогов в папке-источнике сохраняется.
Т.к. в этой папке и всех её подпапках были изображения, то так же в папке был скрытый файл Thumbs.db. Автоматически его удалить не получилось, ни powershell, ни vbs, ни cmd не смогли удалить их, по этому удалил их через поиск.
скрипт 2 - удаление всех пустых каталогов:
#$path = "D:\data"
#dir -Path $path -Recurse | ?{$_.psiscontainer} | sort pspath -Descending | ?{!$ExecutionContext.InvokeProvider.ChildItem.HasChild($_.pspath)} | delили так
$path="D:\data";
$EmptyFolders = ls $path -Recurse | ?{
(ls -Path $_.FullName -Recurse -Force | ?{
$_.PSIsContainer -eq $false
}) -eq $null
};
if ($EmptyFolders -ne $null) {
$EmptyFolders | %{
if (Test-Path $_.FullName) {
$_ | ri -Recurse
}
}
}
Автоматически его удалить не получилось, ни powershell, ни vbs, ни cmd не смогли удалить их »
Поставьте в скрипт команду сброса атрибутов -r, -h, -s для всех (чтобы не мудрствовать лукаво) файлов. После этого удаление пойдёт.
Поставьте в скрипт команду сброса атрибутов -r, -h, -s для всех (чтобы не мудрствовать лукаво) файлов. После этого удаление пойдёт. »
можно поточнее о какой команде и для какого языка идет речь? буду очень признателен.
можно поточнее о какой команде и для какого языка идет речь? »
В любом языке обязана быть команда работы с атрибутами файла (r, т.е. read only; s, т.е. system, h, т.е. hidden -- ну и непринципиальный (как правило) a): их сброс и установка. Даже в DOS-3 была (и до сих пор существует в cmd.exe и может быть использована в командных и пакетных файлах), например attrib -r <имя_файла> -- сброс атрибута rеad-only ("только для чтения") у файла, attrib +s <имя_файла> -- установка атрибута system ("системный"), attrib -s -h -r <имя_файла> -- одновременный сброс атрибутов "Системный", "Скрытый", "Только для чтения".
Поэтому я и дал чисто общую рекомендацию: надо смотреть, как это конкретно реализуется в языке, который вы используете.
Не обязательно сбрасывать атрибуты в отдельном цикле (это лишние накладные расходы): достаточно это делать при первом же обращении к файлу, перед выполнением любых других операций с ним.
Теперь понял.
Спасибо. Попробую посмотреть что с этим можно сделать в powershell, раз уж всё на нём сделано
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.