Jak najlepiej (idiomatycznie) zawieść skrypt perla (uruchomić z -n / -p), gdy nie znaleziono pliku wejściowego?

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

Naprawdę chciałbym, aby skrypt Perla zawiódł, gdy plik nie istnieje. Jaki jest „właściwy” sposób, aby polecenie -p lub -n nie powiodło się, gdy plik wejściowy nie istnieje?

William Pursell
źródło

Odpowiedzi:

6

Przełącznik -p to tylko skrót do owijania swój kod (argument następujący -e) w tej pętli:

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

(-n jest taki sam, ale bez bloku kontynuacji).

<>Operator pusty odpowiada readline *ARGVi który otwiera każdy argument z rzędu w postaci pliku do odczytu z. Nie ma sposobu, aby wpłynąć na obsługę błędów tego niejawnego otwarcia, ale można ustawić ostrzeżenie, które emituje błąd (uwaga, wpłynie to również na kilka ostrzeżeń związanych z przełącznikiem -i):

perl -Mwarnings=FATAL,inplace -pe 1 foo && echo ok
Grinnz
źródło
@ MarkReed inplace to interesująca nas kategoria ostrzeżeń. Nie ma powodu, aby wpływać na inne ostrzeżenia.
Grinnz
Z ostrzeżeń :The presence of the word "FATAL" in the category list will escalate warnings in those categories into fatal errors in that lexical scope.
Grinnz
Tak, inplacejest kategoria; bez niego -Mwarnings=FATALoznacza to FATAL => all, czego nie chcemy. Rozumiem.
Mark Reed,
4

Ustaw flagę w treści pętli, zaznacz flagę w bloku END na końcu onelinera.

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

Pamiętaj, że kończy się niepowodzeniem tylko wtedy, gdy żaden plik nie został przetworzony.

Aby zgłosić problem, gdy nie wszystkie pliki zostały znalezione, możesz użyć czegoś takiego

perl -pe 'BEGIN{ $files = @ARGV} $found++ if eof; ... ;END {die "Some files not found" unless $files == $found}'
choroba
źródło
1
Jeśli twój skrypt ma pobierać pliki jako argumenty, a nie czytać ze standardowego wejścia, byłaby lżejsza alternatywa dla tego rozwiązania BEGIN{die "File not found" unless -f $ARGV[0]}. (Mówię lżejsze, ponieważ nie wymaga to ustawiania flagi i dodawania 2 kodów)
Dada
Zakłada również, że wszystkie pliki mają niezerową długość.
Tanktalus,