Как я выполняю команду в цикле, пока я не вижу некоторую строку в stdout?

Чтобы добавить ответ Эврики, команда vanilla dir не может достичь того, что вы ищете.

C:\Users\jacob>dir /?
Displays a list of files and subdirectories in a directory.

DIR [drive:][path][filename] [/A[[:]attributes]] [/B] [/C] [/D] [/L] [/N]
  [/O[[:]sortorder]] [/P] [/Q] [/R] [/S] [/T[[:]timefield]] [/W] [/X] [/4]

  [drive:][path][filename]
              Specifies drive, directory, and/or files to list.

  /A          Displays files with specified attributes.
  attributes   D  Directories                R  Read-only files
               H  Hidden files               A  Files ready for archiving
               S  System files               I  Not content indexed files
               L  Reparse Points             -  Prefix meaning not
  /B          Uses bare format (no heading information or summary).
  /C          Display the thousand separator in file sizes.  This is the
              default.  Use /-C to disable display of separator.
  /D          Same as wide but files are list sorted by column.
  /L          Uses lowercase.
  /N          New long list format where filenames are on the far right.
  /O          List by files in sorted order.
  sortorder    N  By name (alphabetic)       S  By size (smallest first)
               E  By extension (alphabetic)  D  By date/time (oldest first)
               G  Group directories first    -  Prefix to reverse order
  /P          Pauses after each screenful of information.
  /Q          Display the owner of the file.
  /R          Display alternate data streams of the file.
  /S          Displays files in specified directory and all subdirectories.
  /T          Controls which time field displayed or used for sorting
  timefield   C  Creation
              A  Last Access
              W  Last Written
  /W          Uses wide list format.
  /X          This displays the short names generated for non-8dot3 file
              names.  The format is that of /N with the short name inserted
              before the long name. If no short name is present, blanks are
              displayed in its place.
  /4          Displays four-digit years

Switches may be preset in the DIRCMD environment variable.  Override
preset switches by prefixing any switch with - (hyphen)--for example, /-W.

Кроме того, в качестве альтернативы предложению использовать ("*.txt"), если ваш список файлов включает в себя несколько расширений, вы можете либо исключить разные расширения , либо использовать *.*, чтобы получить все файлы с . в названии. Поиграйте с этим шаром, чтобы получить из него то, что вы хотите.

15
задан Alex Miller 24 September 2008 в 18:53
поделиться

8 ответов

В Perl:

#!/usr/local/bin/perl -w

if (@ARGV != 2)
{
    print "Usage: watchit.pl <cmd> <str>\n";
    exit(1);
}

$cmd = $ARGV[0];
$str = $ARGV[1];

while (1)
{
    my $output = `$cmd`;
    print $output; # or dump to file if desired
    if ($output =~ /$str/)
    {
        exit(0);
    }
}

Пример:

[bash$] ./watchit.pl ls stop
watchit.pl
watchit.pl~
watchit.pl
watchit.pl~
... # from another terminal type "touch stop"
stop 
watchit.pl
watchit.pl~

Вы могли бы хотеть добавить сон там, все же.

13
ответ дан 1 December 2019 в 01:06
поделиться
while (/bin/true); do
  OUTPUT=`/some/command`
  if [[ "x$OUTPUT" != "x" ]]; then
    echo $OUTPUT
    break
  fi

  sleep 1
done
1
ответ дан 1 December 2019 в 01:06
поделиться

Простой способ сделать это было бы

until `/some/command`
do
  sleep 1
done

, обратные галочки вокруг команды делают эти until тест для некоторого вывода, который будет возвращен вместо того, чтобы тестировать значение выхода команды.

0
ответ дан 1 December 2019 в 01:06
поделиться

Существует набор способов сделать это, первое, которое пришло на ум, было:

OUTPUT=""; 
while [ `echo $OUTPUT | grep -c somestring` = 0 ]; do 
  OUTPUT=`$cmd`; 
done

, Где $cmd является Вашей командой для выполнения.

Для heck его, вот версия функции Bash, таким образом, можно назвать это более легко, если это - что-то, что Вы желаете вызвать от интерактивной оболочки регулярно:

function run_until () {
  OUTPUT="";
  while [ `echo $OUTPUT | grep -c $2` = 0 ]; do
    OUTPUT=`$1`;
    echo $OUTPUT;
  done
}

Правовая оговорка: только слегка протестированный, возможно, должен сделать некоторый дополнительный выход и т.д., если Ваши команды имеют много аргументов, или строка содержит специальные символы.

РЕДАКТИРОВАНИЕ : На основе обратной связи от комментария Adam - если Вы не делаете , нуждаются в выводе по любой причине (т.е. не хотят отображать вывод), тогда можно использовать эту более короткую версию с меньшим количеством использования обратных галочек и поэтому меньше служебного:

OUTPUT=0; 
while [ "$OUTPUT" = 0 ]; do 
  OUTPUT=`$cmd | grep -c somestring`;
done

версия функции Bash также:

function run_until () {
  OUTPUT=0; 
  while [ "$OUTPUT" = 0 ]; do 
    OUTPUT=`$1 | grep -c $2`; 
  done
}
11
ответ дан 1 December 2019 в 01:06
поделиться

Я удивлен, что не видел краткую остроту Perl, упомянутую здесь:

perl -e 'do { sleep(1); $_ = `command`; print $_; } until (m/search/);'

Perl является действительно хорошим языком для материала как это. Замена "управляет" с командой, которую Вы хотите неоднократно выполнить. "Поиск" замены с тем, что Вы хотите искать. Если Вы хотите искать что-то с наклонной чертой в нем, то замените m/search/ с m#search строка с /es#.

Кроме того, Perl работает на большом количестве различных платформ, включая Win32, и это будет работать везде, где у Вас есть установка Perl. Просто измените свою команду соответственно.

7
ответ дан 1 December 2019 в 01:06
поделиться
CONT=1; while [ $CONT -gt 0 ]; do $CMD | tee -a $FILE | grep -q $REGEXP; CONT=$? ; done

команда мишени может получить stdout в канале, все еще передавание данных, и -a заставляет его добавить в файл вместо того, чтобы перезаписать его каждый раз. grep -q будет return 0, если было соответствие, 1 иначе и ничего не пишет в stdout. $? возвращаемое значение предыдущей команды, таким образом $CONT будет возвращаемое значение grep в этом случае.

1
ответ дан 1 December 2019 в 01:06
поделиться

РЕДАКТИРОВАНИЕ: Мой исходный ответ предполагал, что "некоторая строка" означает "любую строку". Если необходимо искать определенный, Perl является, вероятно, наилучшим вариантом, так как почти ничто не может разбить Perl когда дело доходит до соответствия REGEX.

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

MATCH=''; while [[ "e$MATCH" == "e" ]]; do MATCH=`COMMAND | grep "SOME_STRING"`; done; echo $MATCH

Замена КОМАНДА с на самом деле управляют для выполнения и SOME_STRING со строкой для поиска. Если SOME_STRING будет найден в выводе КОМАНДЫ, то цикл остановит и распечатает вывод, где SOME_STRING был найден.

ИСХОДНЫЙ ОТВЕТ:

, Вероятно, не лучшее решение (я не хороший программист удара), но это будет работать:-P

RUN=''; while [[ "e$RUN" == "e" ]]; do RUN=`XXXX`; done ; echo $RUN

Просто заменяет XXXX Вашим вызовом команды, например, пытается использовать" эхо ", и это никогда не будет возвращаться (поскольку эхо никогда ничего не печатает к stdout), однако если Вы будете использовать" тест эха то", это завершится сразу и наконец распечатает тест.

1
ответ дан 1 December 2019 в 01:06
поделиться

grep -c 99999 распечатает 99 999 строк контекста для соответствия (я предполагаю, что это будет достаточно):

while true; do /some/command | grep expected -C 99999 && break; done

или

until /some/command | grep expected -C 9999; do echo -n .; done

... это распечатает некоторые хорошие точки для указания на прогресс.

5
ответ дан 1 December 2019 в 01:06
поделиться