[Script] Выполнение команды для каждого элемента списка
Select messages from
# through # FAQ
[/[Print]\]
Goto page 1, 2, 3  Next  :| |:
Total Commander -> Автоматизация Total Commander

#1: [Script] Выполнение команды для каждого элемента списка Author: BatyaLocation: Москва, Россия PostPosted: Wed Dec 31, 2008 11:13
    —
Представляю MultiRun.vbs - выполняет мнократный запуск команды для каждого элемента в файле-списке.
Code:
'=======================================================================================
' Выполнение указанной команды (программы) для каждого элемента файла-списка

' Параметры скрипта:
' 1 - Набор режимов, где каждый режим определяется цифрами по разрядам:
'     1 - обрабатывать каждый список отдельно (0 - умолч.) или синхронно (1),
'     2 - последовательное (0 - умолч.) или параллельное (1) выполнение команд по списку
' 2 и далее - Выполняемая команда (программа) и параметры к ней
' Начало и конец файла-списка определяется заданными ниже символами (набором символов).
'   Команда выполняется для каждого элемента списка, подстановкой этого элемента в
'   местоположение списка.
' В качестве параметра может быть указано текстовое содержимое буфера обмена.
'   Тэг буфера обмена задается в секции скрипта "Изменяемые параметры".
'   Для использования буфера обмена в системе должен быть установлен TCScript.Helper.
' Например, параметры вызова из TC для одновременного фонового извлечения из архивов,
'   пароль к которым находится в буфере обмена, в текущую папку:
'   10 "%ProgramFiles%\WinRar\WinRar.Exe" X -ibck -p### {{%L}} "%P"
'
' Автор  - Batya
' Версия - 1.2
'=======================================================================================
Option Explicit
'================= Изменяемые параметры ================================================
Const ListBegin    = "{{"  'Начало списка
Const ListEnd      = "}}"  'Конец списка
Const ClipboardTag = "###" 'Тэг буфера обмена 
'=======================================================================================
Dim FSO, WSH, Mess, Mode(1), Command, i, L, P, LenListBegin, LenListEnd, Clipboard
Set FSO  = CreateObject("Scripting.FileSystemObject")
Set WSH  = CreateObject("WScript.Shell")

'Задаем массив сообщений
MessDefine
'Проверяем параметры
CheckParams

LenListBegin = Len(ListBegin)
LenListEnd   = Len(ListEnd)

'Выполняем команды по списку
For Each L In SearchList(Command, 0)
  'Тестовая строка - раскомментарить для проверки
  'MsgBox L, vbOKOnly, Mess(5)
  WSH.Run L, 7, (Mode(1) = 0)
Next

'Выход
Quit

'===== Процедуры и функции =============================================================
'Проверка входных параметров
Sub CheckParams
  Dim k, m, lP, n
  With WScript
    If .Arguments.Count = 0 Then
      MsgBox Mess(1), vbCritical + vbOKOnly, Mess(0)
      Quit
    End If
    If .Arguments.Count < 2 Then
      MsgBox Mess(2), vbCritical + vbOKOnly, Mess(0)
      Quit
    End If
    m = .Arguments(0)
    For i = 1 To .Arguments.Count - 1
      lP = WSH.ExpandEnvironmentStrings(.Arguments(i))
      If InStr(lP, " ") > 0 Then lP = """" & lP & """"
      Command = Command & " " & lP
    Next
    Command = Mid(Command, 2)
  End With
  n = UBound(Mode) + 1
  m = Right(String(n, "0") & m, n)
  For i = 0 To n - 1
    k = Left(Right(m, i + 1), 1) 'Берем очередной разряд
    'Проверяем правильность задания каждого режима
    Select Case i
      Case 0
        If IsNumeric(k) Then k = CInt(k)
        If (k=0) Or (k=1) Then Mode(i) = k
      Case 1
        If IsNumeric(k) Then k = CInt(k)
        If (k=0) Or (k=1) Then Mode(i) = k
    End Select
  Next
End Sub

'Поиск в строке тэгов файлов-списков и формирование массива элементов
Function SearchList(pStr, byVal pDepth)
  Dim lList, lL, lPos1, lPos2, lStr, lBegin, lEnd, lList1, lL1, lList2, k, m
  If UCase(ListBegin) = UCase(ListEnd) Then
    'Ищем начало списка
    lPos1 = InStr(1, pStr, ListBegin, vbTextCompare)
    If lPos1 = 0 Then
      SearchList = Array(SearchClipboard(pStr))
      Exit Function
    End If
    'Ищем конец списка
    lPos2 = InStr(lPos1 + LenListBegin, pStr, ListEnd, vbTextCompare)
    If lPos2 = 0 Then
      SearchList = Array(SearchClipboard(pStr))
      Exit Function
    End If
  Else
    'Ищем конец списка
    lPos2 = InStr(1, pStr, ListEnd, vbTextCompare)
    If lPos2 = 0 Then
      SearchList = Array(SearchClipboard(pStr))
      Exit Function
    End If
    'Ищем начало списка
    lPos1 = InStrRev(pStr, ListBegin, lPos2 - 1, vbTextCompare)
    If lPos1 = 0 Then
      SearchList = Array(SearchClipboard(pStr))
      Exit Function
    End If
  End If
  'Файл-список
  lList = Mid(pStr, lPos1 + LenListBegin, lPos2 - lPos1 - LenListBegin)
  'Если файла-списка не существует, выходим
  If Not FSO.FileExists(lList) Then
    MsgBox Mess(3) & " """ & lList & """ " & Mess(4),_
           vbCritical + vbOKOnly, Mess(0)
    Quit
  End If
  'Начало и конец командной строки
  lBegin = Left(pStr, lPos1 - 1)
  lEnd   = Mid(pStr, lPos2 + LenListBegin)
  'Перебираем список
  lList2 = Split(FSO.OpenTextFile(lList, 1, False, -2).ReadAll, vbNewLine)
  m = pDepth
  If pDepth = 0 Then
    pDepth = UBound(lList2)
    m = 0
  End If
  For k = m To pDepth
    lL = lList2(k)
    If lL = "" Then Exit For
    lL = WSH.ExpandEnvironmentStrings(lL)
    If InStr(lL, " ") > 0 Then lL = """" & lL & """"
    'Формируем выходной список в зависимости от режима
    Select Case Mode(0)
      Case 0
        'Рекурсивный поиск списка
        lList1 = SearchList(lBegin & lL & lEnd, 0)
        For Each lL1 In lList1
          lStr = lStr & vbNewLine & lL1
        Next
      Case 1
        'Рекурсивный поиск списка
        lList1 = SearchList(lBegin & lL & lEnd, k)
        lStr   = lStr & vbNewLine & lList1(0)
    End Select
  Next
  SearchList = Split(SearchClipboard(Mid(lStr, Len(vbNewLine) + 1)), vbNewLine)
End Function

'Подстановка текстового значения из буфера обмена
Function SearchClipboard(pStr)
  If UBound(Filter(Array(pStr), ClipboardTag)) >= 0 Then
    SearchClipboard = Replace(pStr, ClipboardTag, GetClipboard)
  Else
    SearchClipboard = pStr
  End If
End Function

'Содержимое буфера обмена
Function GetClipboard()
  If IsEmpty(Clipboard) Then
    GetClipboard = CreateObject("TCScript.Helper").GetTextFromClip
  Else
    GetClipboard = Clipboard
  End If
End Function

'Описание сообщений
Sub MessDefine
  Set Mess = CreateObject("Scripting.Dictionary")
  With Mess
    .Add 0,  "Выполнение программы для списка"
    .Add 1,  "Не указаны параметры!"
    .Add 2,  "Не указана выполняемая команда!"
    .Add 3,  "Файл-список"
    .Add 4,  "не существует!"
    .Add 5,  "Тест командной строки"
  End With
End Sub

'Выход
Sub Quit
  Set Mess = Nothing
  Set WSH  = Nothing
  Set FSO  = Nothing
  WScript.Quit
End Sub

Плюсы:
- Поддержка неограниченного количества списков. Также возможен вариант перечисления файлов-списков в другом файле-списке.
- Поддержка переменных окружения.
- Возможно задание режима обработки элементов списка.
- Возможно задание режима обработки нескольких списков.
- Использование буфера обмена в параметрах.


Last edited by Batya on Sat Feb 06, 2010 19:55; edited 6 times in total

#2:  Author: BatyaLocation: Москва, Россия PostPosted: Wed Dec 31, 2008 12:25
    —
Скрипт поправлен.
Теперь будет корректно отрабатывать конструкция вида "<<<<{файл-список}>>>>", означающая, что файл-список содержит другие файлы-списки.

В планах:
- Выполнение нескольких раздельных команд (например, сначала распаковка каждого из списка архивов, потом удаление архивов).
- Возможность задания диапазона обработки списка (например, при занесении песен в плей-лист Winamp-а для первого элемента надо толкнуть команду без параметров, а для остальных с параметром "/add").

Другие предложения есть?

#3:  Author: BatyaLocation: Москва, Россия PostPosted: Mon Mar 02, 2009 18:32
    —
Исправлен исходный скрипт - добавлена возможность использования в параметрах буфера обмена. Для использования буфера необходимо, чтобы был усталовлен Script Helper.

#4:  Author: VadiMGP PostPosted: Sat Oct 10, 2009 18:39
    —
Попробовал использовать этот скрипт.
Сделал кнопку
Code:
TOTALCMD#BAR#DATA
E:\Downloads\Рапида\house\mrun.vbs
0 "%ProgramFiles%\WinRar\WinRar.Exe" X -ibck <<%L>> "%T"
D:\WINDOWS\System32\WScript.exe
mrun
E:\Downloads\Рапида\house\

-1

Вылетает с ошибкой
Code:
---------------------------
Windows Script Host
---------------------------
Script:   E:\Downloads\Рапида\house\mrun.vbs
Line:   44
Char:   3
Error:   The system cannot find the file specified.
Code:   80070002
Source:    (null)
В чем может быть причина? Ось - Win XP SP2, TC 7.50a

Кстати, заодно ещё вопрос - Если использовать Вместо %L параметр %WL или %UL, то скрипт это примет?

#5:  Author: BatyaLocation: Москва, Россия PostPosted: Mon Oct 12, 2009 09:44
    —
VadiMGP wrote:
В чем может быть причина?
"%ProgramFiles%" в строке "Параметры" надо обрамлять двойными процентами - "%%ProgramFiles%%" - фишка TC.

VadiMGP wrote:
Если использовать Вместо %L параметр %WL или %UL, то скрипт это примет?
Пока не примет, но %WL могу прикрутить. %UL прикрутить, видимо, не получится.

#6:  Author: VadiMGP PostPosted: Mon Oct 12, 2009 12:18
    —
Batya wrote:
%ProgramFiles%" в строке "Параметры" надо обрамлять двойными процентами
Вот ведь позор на мою седую голову - сам сколько раз юзерам TCMenu это талдычил. Smile Спасибо, заработало.

Насчет параметров. %UL - бог с ним, а вот %WL действительно хотелось бы.

#7:  Author: BatyaLocation: Москва, Россия PostPosted: Mon Oct 12, 2009 13:30
    —
VadiMGP wrote:
%WL действительно хотелось бы
Поправил. Должно работать как с %L, так и %WL.
Чтоб весь скрипт не копировать, можно поменять вызов OpenTextFile:
Code:
FSO.OpenTextFile(lList, 1, False, -2)


VadiMGP
P.S. А чем не нравится аутентичное название файла "MultiRun.vbs"?

#8:  Author: VadiMGP PostPosted: Mon Oct 12, 2009 13:49
    —
Batya wrote:
А чем не нравится аутентичное название файла "MultiRun.vbs"?
Я даже не сразу сообразил о чем ты говоришь. Smile Вполне нравится. Просто я начал писать батник mrun.bat. А потом вспомнил, что видел тут скрипт ну и машинально сохранил в mrun.vbs.

#9:  Author: BatyaLocation: Москва, Россия PostPosted: Sat Nov 14, 2009 12:15
    —
Из другой темы:
Rodny wrote:
Напиши, пожалуйста, подробнее про набор режимов.

Набор режимов - это несколько цифр, которые, в зависимости от их знакоместа определяют варианты работы скрипта. Под знакоместом я понимаю место цифры в числе. Например, в числе 345 в первом разряде (количество единиц) стоит 5, во втором (количество десятков) - 4, в третьем (количество сотен) - 3.
Т.о. набор режимов скрипта - это число, где
- цифра в первом разряде определяет режим работы для нескольких списков в команде - обрабатывать каждый список отдельно (0) или синхронно (1) - значение параметра не играет никой роли, если в применяемой команде используется только один список;
- цифра во втором разряде определяет порядок обработки итогового списка команд - последовательно, т.е. друг за другом, с ожиданием окончания работы предыдущей команды, - (0); или параллельно, т.е. все команды выполнятюся одновременно, без ожидания окончания работы предыдущей, - (1).

P.S. Надеюсь, объяснил не заморочено. Так понятно?

#10:  Author: RodnyLocation: Могилёв, Беларусь PostPosted: Sat Nov 14, 2009 18:36
    —
Batya
Спасибо, я не обратил внимание на упоминание о разрядах
/me ушёл посыпать голову пеплом: математик, блин, по образованию Sad

Про несколько списков, имеется в виду "<<<<{файл-список}>>>>"?

#11:  Author: BatyaLocation: Москва, Россия PostPosted: Sat Nov 14, 2009 22:11
    —
Rodny wrote:
Про несколько списков, имеется в виду "<<<<{файл-список}>>>>"?

Нет. Имеются в виду конструкции вида "<<{файл-список 1}>> <<{файл-список 2}>>".
Для таких конструкций если в первом разряде 0, то количество строк списков должно быть одинаковым, и команды будут выполнятся синхронно для строк с одинаковым номером из каждого списка. Если же в первом разряде стоит 1, то количество строк в файлах-списках может быть разным, и выполняться команды будут по строчкам - каждая строка из одного списка с каждой строкой из другого списка.

#12:  Author: RodnyLocation: Могилёв, Беларусь PostPosted: Sat Nov 14, 2009 22:50
    —
Теперь понял, спасибо. Это ж какой функционал можно на одну кнопку повесить...

#13:  Author: BatyaLocation: Москва, Россия PostPosted: Sat Feb 06, 2010 19:54
    —
Из-за невозможности в консоли для собственных нужд использовать символы "<" и ">" поменял значения по умолчанию для набора символов начала и конца списка:
Code:
Const ListBegin    = "{{"  'Начало списка
Const ListEnd      = "}}"  'Конец списка

#14:  Author: Dimsok PostPosted: Thu Oct 30, 2014 10:19
    —
А чтоб имена файлов без путей были - никак?

#15:  Author: FlasherLocation: Москва PostPosted: Thu Oct 30, 2014 21:11
    —
Dimsok
Напрашивается вопрос - %F вместо %L пробовал?



Total Commander -> Автоматизация Total Commander


output generated using printer-friendly topic mod. All times are GMT + 4 Hours

Goto page 1, 2, 3  Next  :| |:
Page 1 of 3

Powered by phpBB © 2001, 2005 phpBB Group