Проблема с диалоговым окном bash (Whiptail )Индикатор выполнения

#!/usr/bin/perl -w

use strict;
use File::Find ();

sub wanted;
sub process_file ($@);

my $dirfile = shift;    # First argument is the filename containing the list
                        # of directories.

my $pattern = shift;    # Second arg is a perl RE containing the pattern to search
                        # for. Remember to single-quote it on the command line.

# Read in the @dirs array from $dirfile
#
# A NUL-separated file is best, just in case any of the directory names
# contained line-feeds.  If you're certain that could never happen, a
# plain-text LF-separated file would do.
#
# BTW, you can easily generate a NUL-separated file from the shell with:
#    printf "%s\0" dir1 dir2 dir3 dir4 $'dir\nwith\n3\nLFs' > dirs.txt

my @dirs=();

{
  local $/="\0";    # delete this line if you want to use a LF-separated file.
                    # In that case, the {... } block around the code from open to
                    # close is no longer needed.  It's only there so it's possible
                    # to make a local change to the $/ aka $INPUT_RECORD_SEPARATOR
                    # variable.

  open(DIRFILE,"<",$dirfile);
  while() {
    chomp;
    push @dirs, $_;
  };
  close(DIRFILE);
};

File::Find::find({wanted => \&wanted}, @dirs);
exit;

sub wanted {
    my ($dev,$ino,$mode,$nlink,$uid,$gid);

    (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) && -f _ && process_file($_);
}

sub process_file ($@) {

    # This function currently just greps for pattern in the filename passed to
    # it. As the function name implies, it could be used to process the file
    # in any way, not just grep it.

    my $filename = shift;

    # uncomment the return statement below to skip "binary" files.
    # (note this is a workable but fairly crude test.  Perl's File::MMagic
    # module can be used to more accurately identify file types, using the
    # same "magic" file databases as the /usr/bin/file command)

    # return if -B $filename;

    open(FILE,"<",$filename);
    while() {
      print "$filename:$_" if (m/$pattern/o) ;
    };

    close(FILE);
}

Он использует perlи модуль perl File::Find, чтобы делать то же самое, что и ваш find... -exec grep.

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

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

sub process_file ($@) {

    my $filename = shift;
    my $found = 0;

    # uncomment to skip "binary" files:
    return if -B $filename;

    open(FILE,"<",$filename);
    while() {
      if (m/$pattern/o) {
        $found = 1;
        last;
      };
    };

    close(FILE);
    unlink $filename if ($found);
}

Стоит также отметить, что функция wantedв этом скрипте в настоящее время ищет только обычные файлы (тест -f). Функции Perl statи lstatобеспечивают доступ ко всем метаданным файлов, которые findмогут использоваться для сопоставления файлов (uid, gid, perms, size, atime, mtime и т. д. ), поэтому wantedфункция может реплицировать ЛЮБОЙ и все предикаты поиска. подробности см. в perldoc -f statи perldoc -f lstat.

Кстати, сценарий был первоначально сгенерирован find2perl, а затем существенно изменен для )чтения списка каталогов из файла и b )для выполнения grep в коде perl, а не путем разветвления. grepи c )добавляют много комментариев. Производительность должна быть почти идентична find... -exec grep, потому что grep не может открывать файлы или выполнять сопоставление с шаблоном регулярного выражения значительно быстрее, чем это может сделать perl. Это может быть даже быстрее.

Кстати, find2perlраньше включался в perl,но начиная с perl 5.22 он был удален, и теперь его можно найти на CPAN по адресу find2perl

0
16.09.2021, 20:36
1 ответ

Думаю, вы хотите что-то сделать в этом направлении:

msgs=("Preparing install..."
      "Starting Nginx installation..."
     ...
     )
commands=("sudo apt-get update -y"
          "sudo apt-get install nginx -y"
         ...
         )

n=${#commands[@]}
i=0
while [ "$i" -lt "$n" ]; do
    pct=$(( i * 100 / n ))
    echo XXX
    echo $i
    echo "${msgs[i]}"
    echo XXX
    echo "$pct"
    eval "${commands[i]}"
    i=$((i + 1))
done | whiptail --title "Gauge" --gauge "Please wait..." 10 60 0

Главное здесь — два массива, один для сообщений, другой для команд. Обычно вы хотите использовать полный массив для одной командной строки (см. Как мы можем запустить команду, хранящуюся в переменной? ), но у нас нет 2D-массивов, поэтому их можно хранить в виде строк в eval.

(Я не исправил это, чтобы получить правильные проценты, уже поздно.)

0
16.09.2021, 21:22

Теги

Похожие вопросы