Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Перенос файлов старше N дней (http://forum.oszone.net/showthread.php?t=286522)

pogo 15-08-2014 10:21 2389562

Перенос файлов старше 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

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

Kazun 15-08-2014 10:36 2389573

А вывод, что показывает?

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

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

pogo 15-08-2014 10:51 2389577

Вывод Вашей команды:
Цитата:

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 2389579

Move-Item -Destination {md $_.DirectoryName.Replace("$path","$dest") -force}

pogo 15-08-2014 11:20 2389594

Большое спасибо!!
Как раз то что надо.

Можете подсказать, у сего действия имеется какой-то ограниченный уровень вложенности? Сейчас попробовал, и получил не мало подобных ошибок:
Цитата:

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 2389597

Да, он выдает ошибки на папки, поэтому исключите их.

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

pogo 15-08-2014 11:29 2389600

Цитата:

Цитата Kazun
Да, он выдает ошибки на папки, поэтому исключите их. »

А что будет после исключения? Он оставит эту папку на месте?
Просто мне надо перенести всё что старше N дней из папки в папку.

Kazun 15-08-2014 11:31 2389601

Будут только файлы, сам объект папки будет исключен, т.е файлы расположенные в этой будут попадать под перемещение.

pogo 15-08-2014 11:35 2389603

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

Kazun 15-08-2014 11:42 2389607

Немного не так.

Для исключения папок мы используем атрибут 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 2389612

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

pogo 18-08-2014 08:53 2390599

Ещё вариантов решения проблемы никто не подскажет?

pogo 18-08-2014 12:44 2390707

Задачу решил следующими костылями:

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

Цитата:

Цитата pogo
Автоматически его удалить не получилось, ни powershell, ни vbs, ни cmd не смогли удалить их »

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

pogo 19-08-2014 09:27 2391094

Цитата:

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

можно поточнее о какой команде и для какого языка идет речь? буду очень признателен.

mwz 19-08-2014 12:03 2391162

Цитата:

Цитата pogo
можно поточнее о какой команде и для какого языка идет речь? »

В любом языке обязана быть команда работы с атрибутами файла (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 2391341

Теперь понял.
Спасибо. Попробую посмотреть что с этим можно сделать в powershell, раз уж всё на нём сделано


Время: 02:24.

Время: 02:24.
© OSzone.net 2001-