none
Posh: скопировать файлы, в исходном месте оставить только мастер файл и последних четыре файла, всё остальное удалить RRS feed

  • Вопрос

  • Поделюсь, вдруг кому надо будет:
    Изначальная задача выглядела так:
    Archive.bak созданный при царе горохе
    И к нему каждую неделю добавляется инкремент
    Archive1.bak, Archive2.bak ... ArchiveN.bak

    Как бы так собирать батником каждый раз только инкременты, копировать их в надежное место и дропать  оставляя мастер файл в родном каталоге, вместе с четырьмя последними инкрементами.
    http://community.livejournal.com/ru_sysadmins/1232149.html

    код:
    $files = get-childitem | sort lastwritetime
    
    $filesLastFour = $files | select -last 4
    
    $masterFile = Get-ChildItem "bla.xml"
    
    $destination = "d:\temp\"
    
    if ((test-path ($destination + $masterfile.name )) -eq $false) 
    
    	{
    
    # copy $masterfile.name $destination
    
    	write-host copy $masterfile.name $destination
    
    	}
    
    
    
    Foreach ($file in $files) 
    
    	{
    
    	if ($masterfile.Name -eq $file.Name) {continue}	
    
    # copy $file $destination
    
    	write-host copied $file to $destination
    
    	}
    
    
    
    Foreach ($file in $files) 
    
    	{
    
    	if ($filesLastFour -contains $file) {continue}
    
    	if ($masterfile.Name -eq $file.Name) {continue}
    
    # del $file 
    
    	write-host del $file
    
    	}
    
    
    
    
    
    write-host ==== last four
    
    $filesLastFour | select name
    
    
    
    write-host ==== master
    
    $masterFile | select name</em>
    
    
    Изначально сами операции закоментированны, если всё ОК - убрать # из комманд
    Как сделать так, чтобы не копировались файлы которые уже есть в месте назначения  - на домашнее задание =)

    MSBF
    21 октября 2009 г. 9:42

Ответы

  • > Как бы так собирать батником каждый раз только инкременты, копировать их в надежное место и дропать  оставляя мастер файл в родном каталоге, вместе с четырьмя последними инкрементами.

    Из test в test2

    @echo off
    setlocal

    for %%i in ("test\archive*.bak") do set /a cnt+=1
    set /a cnt-=5
    for /l %%i in (%cnt%,-1,1) do (
        if not exist "test2\archive%%i.bak" (move "test\archive%%i.bak" "test2") else (del
    "test\archive%%i.bak" )
    )



    • Помечено в качестве ответа panda_fs2 24 октября 2009 г. 10:59
    21 октября 2009 г. 10:38
  • 01MDM из условия не следует что мастер файл постоянно меняется, скорее наоборот.
    t1 - исходная папка, t2 - назначения. Если в t2 уже присутствуют какие то файлы, они не будут перезаписаны.
    ls t1 -Exclude arc.bak | sort lastwritetime | select -First ((ls t1).count -5) | mv -Destination t2 -ea 0
    AKA Xaegr, MCSE: Security, Messaging; MCITP: Server\Enterprise Administrator; Блог: http://xaegr.wordpress.com
    • Помечено в качестве ответа panda_fs2 22 октября 2009 г. 11:32
    21 октября 2009 г. 15:32
    Модератор

  • > Я не про юникод, слава богу, я про то что файлы могут называться как угодно, хоть archiv_pervii.bak, archiv_vtoroii.bak и т.п.

    Так это реализуется проще некуда:

    @echo off
    
    for /f "skip=4 tokens=*" %%i in ('dir /b /od test\*.bak ^| findstr /v archiv.bak') do (
        echo executing if condition with "%%i"
    )
    


    Просто первоначальное условие можно понять двояко. По ссылке: "Archive1.bak, Archive2.bak ... ArchiveN.bak"
    А это не дочитал: "Понимаю, что надо как то отталкиваться от даты создания файла."
    • Помечено в качестве ответа panda_fs2 24 октября 2009 г. 10:59
    23 октября 2009 г. 21:09

Все ответы

  • Как сделать так, чтобы не копировались файлы которые уже есть в месте назначения  - на домашнее задание =)

    домашнее задание простенькое :P
    If (test-path $destination + $file.name){Break}


    Если ответ Вам помог, нажмите на изображение зеленой галочки - «пометить как ответ». Так же, Вы можете пометить это сообщение как «полезное», нажав на ссылку "проголосовать за полезное сообщение".
    21 октября 2009 г. 9:52
  • > Как бы так собирать батником каждый раз только инкременты, копировать их в надежное место и дропать  оставляя мастер файл в родном каталоге, вместе с четырьмя последними инкрементами.

    Из test в test2

    @echo off
    setlocal

    for %%i in ("test\archive*.bak") do set /a cnt+=1
    set /a cnt-=5
    for /l %%i in (%cnt%,-1,1) do (
        if not exist "test2\archive%%i.bak" (move "test\archive%%i.bak" "test2") else (del
    "test\archive%%i.bak" )
    )



    • Помечено в качестве ответа panda_fs2 24 октября 2009 г. 10:59
    21 октября 2009 г. 10:38
  • 01MDM из условия не следует что мастер файл постоянно меняется, скорее наоборот.
    t1 - исходная папка, t2 - назначения. Если в t2 уже присутствуют какие то файлы, они не будут перезаписаны.
    ls t1 -Exclude arc.bak | sort lastwritetime | select -First ((ls t1).count -5) | mv -Destination t2 -ea 0
    AKA Xaegr, MCSE: Security, Messaging; MCITP: Server\Enterprise Administrator; Блог: http://xaegr.wordpress.com
    • Помечено в качестве ответа panda_fs2 22 октября 2009 г. 11:32
    21 октября 2009 г. 15:32
    Модератор
  • 01MDM из условия не следует что мастер файл постоянно меняется, скорее наоборот.
    t1 - исходная папка, t2 - назначения. Если в t2 уже присутствуют какие то файлы, они не будут перезаписаны.
    ls t1 -Exclude arc.bak | sort lastwritetime | select -First ((ls t1).count -5) | mv -Destination t2 -ea 0
    AKA Xaegr, MCSE: Security, Messaging; MCITP: Server\Enterprise Administrator; Блог: http://xaegr.wordpress.com

    Вы меня сделали =)
    MSBF
    22 октября 2009 г. 11:32
  • > 01MDM из условия не следует что мастер файл постоянно меняется, скорее наоборот.

    Так у меня он и не меняется. Archiv.bak всегда остается на месте. Другое дело, что я сразу не понял, что нужен не батник. А в остальном, если файлы с инкрементами идут по порядку, то и батник отрабатывает правильно.

    Но и `select lastwritetime` не гарантирует правильное решение. Файл может быть создан или изменен позже, а порядковый номер иметь меньший. Например после выполнения остаются  archiv.bak, archiv6.bak-archiv9.bak. При следующем заполнении каталога более свежие файлы будут иметь меньший
    порядковый номер от 1 до 5.
    23 октября 2009 г. 9:17
  • > 01MDM из условия не следует что мастер файл постоянно меняется, скорее наоборот.

    Так у меня он и не меняется. Archiv.bak всегда остается на месте. Другое дело, что я сразу не понял, что нужен не батник. А в остальном, если файлы с инкрементами идут по порядку, то и батник отрабатывает правильно.

    Но и `select lastwritetime` не гарантирует правильное решение. Файл может быть создан или изменен позже, а порядковый номер иметь меньший. Например после выполнения остаются  archiv.bak, archiv6.bak-archiv9.bak. При следующем заполнении каталога более свежие файлы будут иметь меньший
    порядковый номер от 1 до 5.

    В оригинале человек хотел именно батник, но ему дали решение на ПШ, как более результативное.

    а по поводу второго пункта - так время модификации файла всё-равно будет более позднее чем у других, это раз;
    во вторых никто не говорил что новые инкременты будут начинать нумерацию снова с единицы.
    ну и в третих решение на ПШ позволяет работать с абсолютно любыми названиями файлов.
    MSBF
    23 октября 2009 г. 14:28
  • Я с вами не спорю. Но:

    > а по поводу второго пункта - так время модификации файла всё-равно будет более позднее чем у других

    Да, но если к более ранним не было доступа.
     
    Я вопрос понял так, что файлы должны перемещаться/удаляться в зависимости от значения цифрового индекса: "вместе с четырьмя последними инкрементами "

    Если бы критерием служило время модификации или создания, то тогда бы сортировка шла исходя из этого. Это тоже просто.

    > никто не говорил что новые инкременты будут начинать нумерацию снова с единицы.

    Тогда теряется сам смысл нумерации файлов. Значит оставшиеся четыре надо переименовывать (Archiv(1..4).bak)

    > решение на ПШ позволяет работать с абсолютно любыми названиями файлов.

    Cmd тоже работает в юникодном режиме (cmd /u), тоже utf16, и тоже с любыми названиями. Через переменную %cmdcmdline% можно определить режим и перезапустить батник в юникоде. Или сразу запускать cmd /u arch.cmd
    23 октября 2009 г. 15:07
  • Я с вами не спорю. Но:

    > а по поводу второго пункта - так время модификации файла всё-равно будет более позднее чем у других

    Да, но если к более ранним не было доступа.
     
    Я вопрос понял так, что файлы должны перемещаться/удаляться в зависимости от значения цифрового индекса: "вместе с четырьмя последними инкрементами "

    Если бы критерием служило время модификации или создания, то тогда бы сортировка шла исходя из этого. Это тоже просто.

    > никто не говорил что новые инкременты будут начинать нумерацию снова с единицы.

    Тогда теряется сам смысл нумерации файлов. Значит оставшиеся четыре надо переименовывать (Archiv(1..4).bak)

    > решение на ПШ позволяет работать с абсолютно любыми названиями файлов.

    Cmd тоже работает в юникодном режиме (cmd /u), тоже utf16, и тоже с любыми названиями. Через переменную %cmdcmdline% можно определить режим и перезапустить батник в юникоде. Или сразу запускать cmd /u arch.cmd

    И я с Вами тоже, просто объясняю исходные условия.
    Мне кажется что дата модификации более часто встречающийся критерий, чем нумерация.

    Нет, не теряется, ибо как-то надо отличать мастер файл и инкременты, и это не обязательно просто увеличение номера на едницу (мы ведь кстати не знаем системы нумерации ;)), а может быть и дата, и причем не обязательно в виде YYYYMMDDHHmm, а в более сложных вариантах (например человеко-читаемый YYYY-MM-DD_HH-mm, который cmd маловероятно что осилит). А с переименованием Вы что-то загнули, ибо если у нас файлы будут переименовываться (опять-таки зачем?!) то при попытке перемещения их в архив они затрут копии предыдущей итерации (которые тоже были 1..4.bak).

    Я не про юникод, слава богу, я про то что файлы могут называться как угодно, хоть archiv_pervii.bak, archiv_vtoroii.bak и т.п.
    MSBF
    23 октября 2009 г. 19:00

  • > Я не про юникод, слава богу, я про то что файлы могут называться как угодно, хоть archiv_pervii.bak, archiv_vtoroii.bak и т.п.

    Так это реализуется проще некуда:

    @echo off
    
    for /f "skip=4 tokens=*" %%i in ('dir /b /od test\*.bak ^| findstr /v archiv.bak') do (
        echo executing if condition with "%%i"
    )
    


    Просто первоначальное условие можно понять двояко. По ссылке: "Archive1.bak, Archive2.bak ... ArchiveN.bak"
    А это не дочитал: "Понимаю, что надо как то отталкиваться от даты создания файла."
    • Помечено в качестве ответа panda_fs2 24 октября 2009 г. 10:59
    23 октября 2009 г. 21:09
  • В общем ладно, кому надо копировать инкрементые архивы - имеют аж четыре варианта действий =)
    Всем спасибо.


    MSBF
    24 октября 2009 г. 11:02