Найти самое длинное имя файла

Perl был разработан и создан именно для такого рода задач. Его прозвище было «патологический эклектичный мусорный лист».

Прочтите документацию по perlform .Что вы делаете, так это читаете ваши данные (скажем, построчно), анализируете их, вставляете в переменные, а затем вводите команду write , которая выводит текущие данные на основе формата , который вы определили.

Для ваших данных у вас может быть формат для заголовка:

format STDOUT_TOP = 
Virtual_Machine    Vdsks               size      Physical_Disks
-----------------  ------------------  --------- ---------------
.

и другой для каждой строки вывода:

format STDOUT = 
@<<<<<<<<<<<<<<<<  @<<<<<<<<<<<<<<<<<  @>>>>>>>>>>> -
$virtualmachine,   @vdisk,             @vdisk_size
@<<<<<<<<<<<<<<<<  @<<<<<<<<<<<<<<<~~  @>>>>>>>>>~~ -
$#vdisk<0?'':$virtualmachine,   shift(@vdisk), shift(@vdisk_size)
@<<<<<<<<<<<<<<<<  -                                ^<<<<<<<<<<<<~~
$#disks<0?'':$virtualmachine,                       shift(@disks)

.

Я не уверен, как вы получаете свои данные, но предположим, что они находятся в одном файле, разделенном двумя символами новой строки. Каждый хост представляет собой блок строк:

Virtual Machine  Test1 status  Running.
Assigned Server  OVS001.local
Virtual Disk  Test_DISK1 (30) size  61GB
Physical Disk  HITACHI (110)
Physical Disk  HITACHI (113)
Physical Disk  HITACHI (111)

Virtual Machine  Test status  Running.
Assigned Server  OVS002.local
Virtual Disk  Test_DISK1 (30) size  41GB
Physical Disk  HITACHI (110)
Physical Disk  HITACHI (113)
Physical Disk  HITACHI (111)

Вы устанавливаете свой символ-разделитель ввода следующим образом:

$/="\n\n";

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

while (<>) { 
    # process one virtual machine
}

Теперь начинается самое интересное: анализ ввода. Внутри цикла while вы можете сделать следующее:

my @lines=split("\n");
local @disks=(); # initialize
local $virtualmachine="unknown";
local $physicalserver="unknown";
local @vdisk=("unknown");
local @vdisk_size=("unknown");
foreach (@lines) { 
    $virtualmachine = $1 if /^Virtual Machine\s+(\S+)\s+status\s+/;
    $physicalserver = $1 if /^Assigned Server\s+(\S+)/;
    do { push @vdisk,$1; push @vdisk_size,$2; }
       if /^Virtual Disk\s+(\S+).* size\s+(\d+\w+)/;
    push @disks,$1 if /^Physical Disk\s+(.*)/;
}
write;

Анализ грубый, но обычно эффективный.

0
31.10.2018, 18:41
2 ответа
find /path/to/base -type l | awk -F/ 'BEGIN {maxlength = 0; longest = "" } length( $NF ) > maxlength { maxlength = length( $NF ); longest = $NF } END { print "longest was", longest, "at", maxlength, "characters." }'

Чтобы сделать awkболее читаемым:

BEGIN {
   maxlength = 0
   longest = ""
} 

length( $NF ) > maxlength { 
   maxlength = length( $NF )
   longest = $NF
} 
END { 
   print "longest was", longest, "at", maxlength, "characters." 
}

awkпрекрасно справляется с данными с разделителями. Поскольку пути ограничены /s, мы используем это как разделитель полей (с переключателем -F), отслеживаем самое длинное имя, которое мы видели, с помощью переменной longestи его длину в maxlengthпеременная. Некоторая забота и подпитка, чтобы сделать вывод разумным, если ссылки не будут найдены, я оставлю читателю в качестве упражнения.

2
28.01.2020, 04:10

Сzsh:

zmodload zsh/stat
by_link_depth() {
  zstat -A REPLY +link -- ${1-$REPLY}
  REPLY=${REPLY//[^\/]}
}

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

ls -ld -- **/*(D@O+by_link_depth[1])

Выведет список символических ссылок (@), включая скрытые(D)с самой глубокой целью (O+by_link_depth, обратную -сортировку по глубине ссылки, и [1]выберет первую ).

Здесь в/usr/bin:

$ ls -ld -- **/*(D@O+by_link_depth[1])
lrwxrwxrwx 1 root root 59 Oct  9 03:08 mptopdf ->../share/texlive/texmf-dist/scripts/context/perl/mptopdf.pl
$ ls -lUd -- **/*(D@O+by_link_depth[1,3])
lrwxrwxrwx 1 root root 59 Oct  9 03:08 mptopdf ->../share/texlive/texmf-dist/scripts/context/perl/mptopdf.pl*
lrwxrwxrwx 1 root root 61 Oct  9 03:09 pkfix-helper ->../share/texlive/texmf-dist/scripts/pkfix-helper/pkfix-helper*
lrwxrwxrwx 1 root root 60 Oct  9 03:09 mkjobtexmf ->../share/texlive/texmf-dist/scripts/mkjobtexmf/mkjobtexmf.pl*

Если вас интересует только максимальная цель ссылки глубины -, а не символическая ссылка, которая указывает на нее, вы можете запустить zstat +linkвместо ls -ldдля этой символической ссылки или вместо этого вы можете определить resolveи by_depthфункция:

resolve() zstat -A REPLY +link -- ${1-$REPLY}
by_depth() REPLY=${REPLY//[^\/]}

и:

printf '%s\n' **/*(D@O+by_depth+resolve[1])

Где +resolveпереводит символическую ссылку в ее цель для расширения глобуса, а O+by_depthобратная -сортирует по глубине.

Сbash(хотя приведенный ниже код никоим образом не bashспецифичен для )и утилит GNU (ваш -printfуже специфичен для GNU -), вы можете получить что-то похожее с:

find. -type l -printf '%l\0%p\0' | gawk -v RS='\0' -v ORS='\0' -F / '
   {n = NF; getline; if (n > max) {max = n; file = $0}}
   END {if (max) print file}' | xargs -r0 ls -ld

Или только для самой глубокой цели:

find. -type l -printf '%l\0' | gawk -v RS='\0' -F / '
   NF > max {max = NF; target = $0}
   END {if (max) print target}'
0
28.01.2020, 04:10

Теги

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