PDA

Показать полную графическую версию : [решено] Перенос файлов старше N дней


pogo
15-08-2014, 10:21
Доброго времени суток!
Накидал скрипт из пары строк, который должен пройтись по папки и если к файлу последний раз обращались больше чем 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

Заранее спасибо!

Kazun
15-08-2014, 10:36
А вывод, что показывает?

Get-ChildItem $path | Format-Table lastaccess*,name -Auto

И за одно посмотреть, не отключено ли обновление данного атрибута(вроде начиная с Vista отключено по умолчанию):
fsutil behavior query DisableLastAccess

pogo
15-08-2014, 10:51
Вывод Вашей команды:

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.
Подскажите пожалуйста как это побороть?

Kazun
15-08-2014, 10:54
Move-Item -Destination {md $_.DirectoryName.Replace("$path","$dest") -force}

pogo
15-08-2014, 11:20
Большое спасибо!!
Как раз то что надо.

Можете подсказать, у сего действия имеется какой-то ограниченный уровень вложенности? Сейчас попробовал, и получил не мало подобных ошибок:
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 содержащая ещё вложенные папки и файлы.

Kazun
15-08-2014, 11:21
Да, он выдает ошибки на папки, поэтому исключите их.

where { $_.LastAccessTime -le ((Get-Date).AddDays(-5)) -and !$_.PsIsContainer}

pogo
15-08-2014, 11:29
Да, он выдает ошибки на папки, поэтому исключите их. »
А что будет после исключения? Он оставит эту папку на месте?
Просто мне надо перенести всё что старше N дней из папки в папку.

Kazun
15-08-2014, 11:31
Будут только файлы, сам объект папки будет исключен, т.е файлы расположенные в этой будут попадать под перемещение.

pogo
15-08-2014, 11:35
Извините за назойливость, просто хочется окончательно разобраться.
Получается что благодаря этой конструкции: Move-Item -Destination {md $_.DirectoryName.Replace("$path","$dest") -force} все файлы будут переносится с автоматическим сохранением и созданием структуры папок в папке назначения. И данная конструкция не умеет переносить папки, по этому мы их исключаем из переноса?
Я правильно понял?

Kazun
15-08-2014, 11:42
Немного не так.

Для исключения папок мы используем атрибут 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 подходит под условие, а все файлы внутри свежие, что у Вас предусмотрено?

pogo
15-08-2014, 11:49
Честно говоря затрудняюсь ответит...
Просто есть папка гигов в 200, в которой огромная количество папок и файлов в жуткой структуре подпапок.
Мне надо найти ВСЁ что старше N дней\месяцев и перенести оттуда в другую папку с сохранением структуры папок. Т.е. если кому-нибудь понадобится получить файл за 2010 год из этого ужаса, то можно узнать путь где он лежал и вытащить его из папки куда он был перемещён ($dest) по такому же пути (ну понятное дело что сменится корневая папка или диску куда это всё перенесется, но смысл я думаю поняте)

pogo
18-08-2014, 08:53
Ещё вариантов решения проблемы никто не подскажет?

pogo
18-08-2014, 12:44
Задачу решил следующими костылями:

скрипт 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
}
}
}

mwz
18-08-2014, 19:33
Автоматически его удалить не получилось, ни powershell, ни vbs, ни cmd не смогли удалить их »

Поставьте в скрипт команду сброса атрибутов -r, -h, -s для всех (чтобы не мудрствовать лукаво) файлов. После этого удаление пойдёт.

pogo
19-08-2014, 09:27
Поставьте в скрипт команду сброса атрибутов -r, -h, -s для всех (чтобы не мудрствовать лукаво) файлов. После этого удаление пойдёт. »
можно поточнее о какой команде и для какого языка идет речь? буду очень признателен.

mwz
19-08-2014, 12:03
можно поточнее о какой команде и для какого языка идет речь? »

В любом языке обязана быть команда работы с атрибутами файла (r, т.е. read only; s, т.е. system, h, т.е. hidden -- ну и непринципиальный (как правило) a): их сброс и установка. Даже в DOS-3 была (и до сих пор существует в cmd.exe и может быть использована в командных и пакетных файлах), например attrib -r <имя_файла> -- сброс атрибута rеad-only ("только для чтения") у файла, attrib +s <имя_файла> -- установка атрибута system ("системный"), attrib -s -h -r <имя_файла> -- одновременный сброс атрибутов "Системный", "Скрытый", "Только для чтения".

Поэтому я и дал чисто общую рекомендацию: надо смотреть, как это конкретно реализуется в языке, который вы используете.

Не обязательно сбрасывать атрибуты в отдельном цикле (это лишние накладные расходы): достаточно это делать при первом же обращении к файлу, перед выполнением любых других операций с ним.

pogo
19-08-2014, 16:49
Теперь понял.
Спасибо. Попробую посмотреть что с этим можно сделать в powershell, раз уж всё на нём сделано




© OSzone.net 2001-2012