Bash extended globbing

3

Não consigo mostrar APENAS UM arquivo da saída de ls usando bash extended globbing.

De info bash

  If the 'extglob' shell option is enabled using the 'shopt' builtin,
several extended pattern matching operators are recognized.  In the
following description, a PATTERN-LIST is a list of one or more patterns
separated by a '|'.  Composite patterns may be formed using one or more
of the following sub-patterns:

'?(PATTERN-LIST)'
     Matches zero or one occurrence of the given patterns.

'*(PATTERN-LIST)'
     Matches zero or more occurrences of the given patterns.

'+(PATTERN-LIST)'
     Matches one or more occurrences of the given patterns.

'@(PATTERN-LIST)'
     Matches exactly one of the given patterns.

'!(PATTERN-LIST)'
     Matches anything except one of the given patterns.

.

shops -s extglob

ls -l /boot/@(vmlinuz*)
-rw-r--r--  1 root root 1829516 Apr 21  2009 /boot/vmlinuz-2.6.9-89.EL
-rw-r--r--  1 root root 1700492 Apr 21  2009 /boot/vmlinuz-2.6.9-89.ELsmp

ls -l /boot/?(vmlinuz*)
-rw-r--r--  1 root root 1829516 Apr 21  2009 /boot/vmlinuz-2.6.9-89.EL
-rw-r--r--  1 root root 1700492 Apr 21  2009 /boot/vmlinuz-2.6.9-89.ELsmp

Como mostro apenas UM arquivo?

    
por Felipe Alvarez 19.11.2014 / 03:43

2 respostas

2

O Bash não tem recursos para expandir apenas um jogo entre muitos.

O padrão @(foo) corresponde apenas a uma ocorrência do padrão foo . Ou seja, corresponde a foo , mas não a foofoo . Esse formulário sintático é útil para criar ou padrões como @(foo|bar) , que corresponde a foo ou bar . Pode ser usado como parte de padrões mais longos como @(foo|bar)-*.txt , que corresponde a foo-hello.txt , foo-42.txt , bar-42.txt , etc.

Se você quiser usar uma correspondência entre várias, poderá colocar as correspondências em uma matriz e usar um elemento da matriz.

kernels=(vmlinuz*)
ls -l "${kernels[0]}"

As correspondências são sempre classificadas em ordem lexicográfica, portanto, a primeira correspondência será impressa em ordem lexicográfica.

Observe que, se o padrão não corresponder a nenhum arquivo, você receberá uma matriz contendo um único elemento, que é o padrão inalterado:

$ a=(doesnotmatchanything*)
$ ls -l "${a[0]}"
ls: cannot access doesnotmatchanything*: No such file or directory

Defina a opção nullglob para obter uma matriz vazia.

shopt -s nullglob
kernels=(vmlinuz*)
if ((${#kernels[@]} == 0)); then
  echo "No kernels here"
else
  echo "One of the ${#kernels[@]} kernels is ${kernels[0]}"
fi

O Zsh tem recursos convenientes aqui. O qualificador de glob [NUM] faz com que o padrão seja expandido para apenas a NUMth correspondência; a variante [NUM1,NUM2] se expande para as correspondências NUM1th a NUM2th (começando em 1).

% ls -l vmlinuz*([1])
lrwxrwxrwx 1 root root 26 Nov 15 21:12 vmlinuz -> vmlinuz-3.16-0.bpo.3-amd64
% ls -l nosuchfilehere*([1])
zsh: no matches found: nosuchfilehere*([1])

O qualificador de glob N faz com que o padrão seja expandido para uma lista vazia se nenhum arquivo for correspondido.

kernels=(vmlinuz*(N))
if ((#kernels)); then
  ls -l $kernels
else
  echo "No kernels here"
fi

O qualificador de glob om classifica as correspondências aumentando a idade em vez de pelo nome ( m é para a hora da modificação); Om classifica diminuindo a idade. Então vmlinuz*(om[1]) expande para o arquivo de kernel mais recente.

    
por 20.11.2014 / 02:46
3

"um jogo" não significa o que você acha que faz. Significa uma correspondência dentro do padrão , não apenas para retornar um arquivo. ls não tem nenhuma opção como essa. Normalmente, as pessoas fazem coisas como ls |head -1 ou similar.

    
por 19.11.2014 / 03:52