Como posso usar curingas com ls para encontrar arquivos que estão faltando em uma seqüência numérica?

6

Estou tentando listar arquivos ausentes em uma sequência no terminal. Embora muitas respostas existissem aqui, elas não são genéricas o suficiente para que eu conseguisse adaptá-las à minha situação. Então, se você puder fazer uma resposta genérica o suficiente para trabalhar para mais pessoas, por favor, faça isso.

Estou fazendo ls {369..422}.avi >/dev/null para listar arquivos ausentes, mas não consigo usar * para corresponder a qualquer coisa que termine com .avi. Como posso fazer isso?

Os números não estão no final do arquivo, mas no meio. Então eu preciso de algo como *numbers*.avi

    
por Freedo 13.09.2017 / 14:37

4 respostas

8
ls *{369..422}*.avi >/dev/null

Isso primeiro gerará padrões como

*369*.avi
*370*.avi
*371*.avi
*372*.avi
*373*.avi
*374*.avi

através da expansão da chave e, em seguida, ls será executado com esses padrões, o que fornecerá uma mensagem de erro para cada padrão que não puder ser expandido para um nome no diretório atual.

Como alternativa, se você não tiver arquivos que contenham * em seus nomes:

for name in *{369..422}*.avi; do
    case "$name" in 
        '*'*) printf '"%s" not matched\n' "$name" ;;
    esac
done

Isso depende do fato de que o padrão permanece não expandido se não corresponder a um nome no diretório atual. Isso permite que você faça algo útil para os arquivos ausentes, sem recorrer à análise das mensagens de erro de ls .

    
por 13.09.2017 / 14:44
3

Se você quiser *numbers*.avi , você pode fazer:

ls *[0-9]*.avi

O [0-9] especifica uma classe de caracteres que consiste em todos os caracteres entre 0 e 9 em sua localidade. Isso deveria ser todos os números. Portanto, você deseja corresponder 0 ou mais caracteres ( * ), depois um número [0-9] e, em seguida, 0 ou mais caracteres novamente ( * ).

Se você precisar ter mais de um número em sequência, use:

ls *[0-9][0-9]*.avi

Finalmente, se você tiver arquivos em ordem numérica e apenas quiser encontrar os que faltam, você também pode escrever um pequeno loop:

for avi in {369..422}.avi; do [ -e "$avi" ] || echo "$avi missing"; done
    
por 13.09.2017 / 14:45
3

Para listar quais dos padrões *{369..422}*.avi não correspondem a nenhum arquivo, com zsh , você poderia fazer:

for p (\*{369..422}\*.avi) () {(($#)) || echo $p} $~p(N[1])

Ou mais detalhadamente:

for p (\*{369..422}\*.avi) () {
  if (($#)); then
    echo "$# file(s) matching $p"
  else
    echo >&2 No file matching $p
  fi
} $~p(N)

Para arquivos que seguem um padrão fixo como: foo-123-bar.avi , você também pode fazer:

expected=(foo-{369..422}-bar.avi)
actual=($^expected(N))
missing=(${expected:|actual})
print -l $missing

Alguns dos recursos zsh específicos nele:

  • x{1..20}y brace expansion expandindo para x1y , x2y .... Copiado por alguns outros shells desde.
  • for var (values) cmd : formato abreviado de for loop
  • () compound-command args : função anônima como em muitos outros idiomas.
  • $~p : trata o conteúdo de $p como glob (outras shells fazem isso por padrão e até mesmo a divisão de palavras!)
  • (N[1]) : qualificador glob para globs expandir para nenhum argumento quando eles não correspondem a nenhum arquivo. [1] seleciona o primeiro arquivo correspondente apenas porque apenas um deles informa se houve alguma correspondência.
  • $^array : expansão parecida com brace para os elementos em uma matriz
  • ${array1:|array2} : disjunção de matriz
  • print -l : imprimir em linhas
por 13.09.2017 / 16:06
0

Você pode tentar: ls *{369..422}*.avi

    
por 13.09.2017 / 14:43

Tags