Qual a melhor (idioma) para falhar o script perl (executado com -n / -p) quando o arquivo de entrada não foi encontrado?

11
$ perl -pe 1 foo && echo ok
Can't open foo: No such file or directory.
ok

Eu realmente gostaria que o script perl falhasse quando o arquivo não existe. Qual é a maneira "correta" de fazer com que -p ou -n falhe quando o arquivo de entrada não existe?

William Pursell
fonte

Respostas:

6

A opção -p é apenas um atalho para agrupar seu código (o argumento após -e) neste loop:

LINE:
  while (<>) {
      ...             # your program goes here
  } continue {
      print or die "-p destination: $!\n";
  }

(-n é o mesmo, mas sem o bloco continuar.)

O <>operador vazio é equivalente a readline *ARGV, e isso abre cada argumento sucessivamente como um arquivo para leitura. Não há como influenciar o tratamento de erros dessa abertura implícita, mas você pode fazer com que o aviso seja fatal (observe, isso também afetará vários avisos relacionados à opção -i):

perl -Mwarnings=FATAL,inplace -pe 1 foo && echo ok
Grinnz
fonte
O @MarkReed inplace é a categoria de avisos em que estamos interessados. Não há motivo para afetar outros avisos.
Grinnz 6/12/19
Dos avisos :The presence of the word "FATAL" in the category list will escalate warnings in those categories into fatal errors in that lexical scope.
Grinnz 6/12/19
Certo, inplaceé a categoria; sem ele, -Mwarnings=FATALsignifica FATAL => all, o que não queremos. Entendi.
Mark Reed
4

Defina uma bandeira no corpo do loop, verifique a bandeira no bloco END no final do oneliner.

perl -pe '$found = 1; ... ;END {die "No file found" unless $found}' -- file1 file2

Observe que ele só falha quando nenhum arquivo foi processado.

Para relatar o problema quando nem todos os arquivos foram encontrados, você pode usar algo como

perl -pe 'BEGIN{ $files = @ARGV} $found++ if eof; ... ;END {die "Some files not found" unless $files == $found}'
choroba
fonte
11
Se seu script deve usar arquivos como argumentos em vez de ler a partir de stdin, uma alternativa mais leve a essa solução seria BEGIN{die "File not found" unless -f $ARGV[0]}. (Digo mais leve, porque não envolve a definição de uma bandeira e a adição de 2 códigos)
Dada
Também assume que todos os arquivos têm tamanho diferente de zero.
Tanktalus 6/12/19