Discussion:
useless use of cat? #ShellCheck
(zu alt für eine Antwort)
Christian Garbs
2020-12-13 16:38:50 UTC
Permalink
Mahlzeit!

Ich habe hier in einem alten Skript folgendes stehen:

#!/bin/sh
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl

Das hielt ich für besonders schlau, weil ich so entweder mit STDIN
arbeiten kann ($1 nicht gesetzt) oder mit einer Datei (Dateiname aus
$1).

ShellCheck warnt jetzt freundlich (grüne Farbe ;-), dass ich doch
lieber nicht cat nehmen sollte:

$ shellcheck script.sh

In both.sh line 2:
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl
^-- SC2002: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead.


Ich weiß, dass das nur eine Warnung ist und ShellCheck ist sich selber
ja auch leicht unsicher ("consider […] instead").

Gibt's ne einfache Möglichkeit, das Skript elegent umzuschreiben?

- Ein ausformuliertes if ist mir zu umständlich.

- './anderes-skript.pl < "${1:--}"' klappt natürlich nicht

Hat da jemand einen Trick parat?

Gruß
Christian

PS: Das ist ein Perlskript -- je nachdem, wie das implementiert ist,
könnte './anderes-skript.pl "${1:--}"' funktionieren. Ich wollte
das aber generell fragen, unabhängig von Perl ;-)
--
....Christian.Garbs....................................https://www.cgarbs.de
Bitte beachten Sie auch die Rückseite dieses Schreibens!
Jan Novak
2020-12-14 07:37:51 UTC
Permalink
Post by Christian Garbs
Mahlzeit!
#!/bin/sh
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl
Rein Interesshalber: Was genau passiert damit, bzw. was ist die
Anwendung / Idee dahinter?


Jan
Christian Garbs
2020-12-14 08:15:50 UTC
Permalink
Mahlzeit!
Post by Jan Novak
Post by Christian Garbs
#!/bin/sh
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl
Rein Interesshalber: Was genau passiert damit, bzw. was ist die
Anwendung / Idee dahinter?
- Wenn $1 gesetzt ist, ist das die Datei, die an anderes-skript.pl
verfüggert wird.

- Wenn $1 nicht gesetzt ist, wird '-' ersetzt, dann wird stdin an
anderes-skript.pl verfüttert.


Ich kann das gezeigt Skript also entweder aufrufen als:

$ ls | das-skript

oder

$ das-skript irgendeine.datei

Gruß
Christian
--
....Christian.Garbs....................................https://www.cgarbs.de
It's not whether you win or lose, it's how you look playing the game.
Ulli Horlacher
2020-12-14 08:22:55 UTC
Permalink
Post by Christian Garbs
Mahlzeit!
Post by Jan Novak
Post by Christian Garbs
#!/bin/sh
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl
Rein Interesshalber: Was genau passiert damit, bzw. was ist die
Anwendung / Idee dahinter?
- Wenn $1 gesetzt ist, ist das die Datei, die an anderes-skript.pl
verfüggert wird.
- Wenn $1 nicht gesetzt ist, wird '-' ersetzt, dann wird stdin an
anderes-skript.pl verfüttert.
$ ls | das-skript
oder
$ das-skript irgendeine.datei
Geht auch so:

***@juhu:~: cat zz
#!/bin/sh

cat -- "$@" | tee /dev/tty | wc

***@juhu:~: ./zz # ich tipp hier ein: blubb [ENTER] bla [ENTER] [Ctrl-D]
blubb
blubb
bla
bla
2 2 10

***@juhu:~: ./zz zz
#!/bin/sh

cat -- "$@" | tee /dev/tty | wc
3 9 43
--
Ullrich Horlacher Server und Virtualisierung
Rechenzentrum TIK
Universitaet Stuttgart E-Mail: ***@tik.uni-stuttgart.de
Allmandring 30a Tel: ++49-711-68565868
70569 Stuttgart (Germany) WWW: http://www.tik.uni-stuttgart.de/
Christian Garbs
2020-12-15 18:54:43 UTC
Permalink
Mahlzeit!
Post by Christian Garbs
Post by Christian Garbs
Post by Jan Novak
Post by Christian Garbs
#!/bin/sh
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl
Rein Interesshalber: Was genau passiert damit, bzw. was ist die
Anwendung / Idee dahinter?
- Wenn $1 gesetzt ist, ist das die Datei, die an anderes-skript.pl
verfüggert wird.
- Wenn $1 nicht gesetzt ist, wird '-' ersetzt, dann wird stdin an
anderes-skript.pl verfüttert.
$ ls | das-skript
oder
$ das-skript irgendeine.datei
[…]
Post by Christian Garbs
#!/bin/sh
Super, das nehm ich.

ShellCheck gibt in der Konstellation Ruhe, vermutlich weil eine
Eingabeumleitung mit "$@" als Quelle keine Option ist.

Danke!
Christian
--
....Christian.Garbs....................................https://www.cgarbs.de
Ich bin keine Signatur, ich putze hier nur!
Ulli Horlacher
2020-12-14 08:14:53 UTC
Permalink
Post by Christian Garbs
#!/bin/sh
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl
Das hielt ich für besonders schlau, weil ich so entweder mit STDIN
arbeiten kann ($1 nicht gesetzt) oder mit einer Datei (Dateiname aus
$1).
Gibt's ne einfache Möglichkeit, das Skript elegent umzuschreiben?
Wieso, was stoert dich daran?
Es funktioniert doch wie gewuenscht und ist uebersichtlich?
Post by Christian Garbs
PS: Das ist ein Perlskript -- je nachdem, wie das implementiert ist,
könnte './anderes-skript.pl "${1:--}"' funktionieren. Ich wollte
das aber generell fragen, unabhängig von Perl ;-)
Ne, das da oben ist eindeutig sh :-)
In Perl waere das "while (<>) { ..."
--
Ullrich Horlacher Server und Virtualisierung
Rechenzentrum TIK
Universitaet Stuttgart E-Mail: ***@tik.uni-stuttgart.de
Allmandring 30a Tel: ++49-711-68565868
70569 Stuttgart (Germany) WWW: http://www.tik.uni-stuttgart.de/
Christian Garbs
2020-12-15 18:59:06 UTC
Permalink
Mahlzeit!
Post by Ulli Horlacher
Post by Christian Garbs
#!/bin/sh
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl
Das hielt ich für besonders schlau, weil ich so entweder mit STDIN
arbeiten kann ($1 nicht gesetzt) oder mit einer Datei (Dateiname aus
$1).
Gibt's ne einfache Möglichkeit, das Skript elegent umzuschreiben?
Wieso, was stoert dich daran?
Es funktioniert doch wie gewuenscht und ist uebersichtlich?
Die ShellCheck-Warnung, sobald ich das Skript im emacs öffne.
Also nichts wirklich dringendes, ich wollte nur dazulernen ;-)
Post by Ulli Horlacher
Post by Christian Garbs
PS: Das ist ein Perlskript -- je nachdem, wie das implementiert ist,
könnte './anderes-skript.pl "${1:--}"' funktionieren. Ich wollte
das aber generell fragen, unabhängig von Perl ;-)
Ne, das da oben ist eindeutig sh :-)
Das das meinte das Perlskript ;-)
Dieser Satz ist optimierungsbedürftig, der ursprüngliche auch.
Post by Ulli Horlacher
In Perl waere das "while (<>) { ..."
Genau.

Aber ich habe gerade mal nachgesehen: Das erste Perlskript macht tatsächlich
explizit "while (my $line = <STDIN>) {", was auch immer mich damals
geritten hat. So gesehen hat die Pipe im äußeren Skript schon ihre
Berechtigung.

Das vorgeschlagene 'cat -- "$@" | ...' funktioniert prima und
ShellCheck ist ruhig.

Gruß
Christian
--
....Christian.Garbs....................................https://www.cgarbs.de
Outrageous fantasy warriors battle the limitations of their computers in...
Warhammer 640K.
Stefan Reuther
2020-12-14 08:20:30 UTC
Permalink
Post by Christian Garbs
ShellCheck warnt jetzt freundlich (grüne Farbe ;-), dass ich doch
$ shellcheck script.sh
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl
^-- SC2002: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead.
[...]
Post by Christian Garbs
Gibt's ne einfache Möglichkeit, das Skript elegent umzuschreiben?
Über die Warnung würde ich mir weniger Gedanken machen als darüber, wie
relevant es ist, dass anderes-skript.pl das Original-stdin bekommt.
Also: wenn's eine Datei ist, soll es seekable sein; wenn's stdin ist,
soll es sehen, ob das ein tty ist.

Dann wäre
test -n "$1" && exec <$1
./anderes-skript.pl | ./noch-eins.pl
eine mögliche Lösung.

Aber ansonsten würde ich's wahrscheinlich so lassen.


Stefan
Torsten Berger
2020-12-14 08:37:49 UTC
Permalink
Hallo Christian,
Post by Christian Garbs
#!/bin/sh
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl
Wie siehts damit aus?

#!/bin/sh

[ -f "$FILE" ] || FILE="-"
cat $FILE | ....

Bye Torsten.
--
PGP public key:
http://pool.sks-keyservers.net/pks/lookup?op=get&search=0x983B7EA7E3FC9051
Helmut Waitzmann
2020-12-14 21:52:55 UTC
Permalink
Post by Torsten Berger
Post by Christian Garbs
#!/bin/sh
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl
Wie siehts damit aus?
#!/bin/sh
[ -f "$FILE" ] || FILE="-"
cat $FILE | ....
Bye Torsten.
Nochmal zitiert: 
Post by Torsten Berger
Wie siehts damit aus?
Ich vermute, das stellt den Shell‐Skript‐Prüfer nicht
zufriedener als das OP. 
Torsten Berger
2020-12-14 22:20:48 UTC
Permalink
Post by Helmut Waitzmann
Post by Torsten Berger
Wie siehts damit aus?
Ich vermute, das stellt den Shell‐Skript‐Prüfer nicht
zufriedener als das OP.
...dann vermute weiter.

Bye.
--
PGP public key:
http://pool.sks-keyservers.net/pks/lookup?op=get&search=0x983B7EA7E3FC9051
Christian Garbs
2020-12-15 19:03:07 UTC
Permalink
Mahlzeit!
Post by Torsten Berger
Post by Helmut Waitzmann
Post by Torsten Berger
Wie siehts damit aus?
Ich vermute, das stellt den Shell‐Skript‐Prüfer nicht
zufriedener als das OP.
...dann vermute weiter.
Er hat richtig vermutet.

Vermutlich weil zwischen "cat ${1:--}" und "cat $FILE" inhaltlich kein
Unterschied besteht, solange die Inhalte der Variablen nicht konstant
und dem Prüftool bekannt sind.

Gruß
Christian
--
....Christian.Garbs....................................https://www.cgarbs.de
Die Antwort auf alle Fragen scheint nicht mehr 42 sondern
news.cis.dfn.de zu sein. (Frank Kloeker in de.comm.provider.misc)
Christian Garbs
2020-12-15 18:59:54 UTC
Permalink
Mahlzeit!
Post by Torsten Berger
Post by Christian Garbs
#!/bin/sh
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl
Wie siehts damit aus?
#!/bin/sh
[ -f "$FILE" ] || FILE="-"
cat $FILE | ....
Da bringt ShellCheck die gleiche Warnung, ist also so wie vorher.

Gruß
Christian
--
....Christian.Garbs....................................https://www.cgarbs.de
BEWEIS DURCH VOLLSTÄNDIGE INTUITION: Das sieht man doch sofort!
Helmut Waitzmann
2020-12-16 00:29:07 UTC
Permalink
Post by Torsten Berger
Post by Christian Garbs
#!/bin/sh
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl
Wie siehts damit aus?
Das ist nicht gleichbedeutend mit dem OP: 


Wenn im OP als Parameter ein Dateiname angegeben wird, der keine
reguläre Datei sondern beispielsweise ein Gerät bezeichnet, wirft
Post by Torsten Berger
[ -f "$FILE" ] || FILE="-"
den Dateinamen weg und tauscht ihn durch ein «-» aus, was bewirkt,
dass «cat» nicht die durch den Parameter angegebene
(nicht‐reguläre) Datei sondern die Standardeingabe liest. 
Post by Torsten Berger
cat $FILE | ....
«$FILE» zerbricht den Dateinamen in mehrere Teile, wenn er
Leerzeichen, Tabulatoren oder Zeilenwechsel enthält.  Falls der
Dateiname nur aus solchen Zeichen besteht, bleibt nichts mehr
übrig.  Das ist beides im OP nicht der Fall. 

David Haller
2020-12-14 08:48:26 UTC
Permalink
Post by Christian Garbs
#!/bin/sh
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl
Das hielt ich für besonders schlau, weil ich so entweder mit STDIN
arbeiten kann ($1 nicht gesetzt) oder mit einer Datei (Dateiname aus
$1).
ShellCheck warnt jetzt freundlich (grüne Farbe ;-), dass ich doch
$ shellcheck script.sh
cat "${1:--}" | ./anderes-skript.pl | ./noch-eins.pl
^-- SC2002: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead.
Ich weiß, dass das nur eine Warnung ist und ShellCheck ist sich selber
ja auch leicht unsicher ("consider [?] instead").
Gibt's ne einfache Möglichkeit, das Skript elegent umzuschreiben?
- Ein ausformuliertes if ist mir zu umständlich.
- './anderes-skript.pl < "${1:--}"' klappt natürlich nicht
Freilich klappt das, s.u. ;)
Post by Christian Garbs
Hat da jemand einen Trick parat?
in="${1:--}"
foo "$in"

stellt zumindest mal shellcheck zufrieden, nur frisst längst nicht
jedes Programm auch "-" als "STDIN"-Platzhalter-Dateiname...

An der Stelle würde ich shellcheck schlicht als überfordert ignorieren.
Post by Christian Garbs
PS: Das ist ein Perlskript -- je nachdem, wie das implementiert ist,
könnte './anderes-skript.pl "${1:--}"' funktionieren. Ich wollte
das aber generell fragen, unabhängig von Perl ;-)
Bei Perl gibbet da wat mit ARGV, das beides frisst ;) Naja, fast:

$ cat t.pl
while(<ARGV>) { print; print STDERR "\$ARGV=$ARGV\n" }
$ echo b > b; echo c > c
$ echo "a" | perl t.pl
a
$ARGV=-
$ echo "a" | perl t.pl b c
b
$ARGV=b
c
$ARGV=c

Um im letzteren Fall auch noch STDIN reinzubekommen muß man IIRC tricksen.

Ah, so geht's:

$ cat t.pl
while(<STDIN>) { print; print STDERR "\$ARGV=$ARGV\n"; }
while(<ARGV>) { print; print STDERR "\$ARGV=$ARGV\n"; }
$ echo "a" | perl t.pl b c
a
$ARGV=
b
$ARGV=b
c
$ARGV=c
$

Interessant ist der Effekt, wenn man in der ersten Zeile '<STDIN>'
durch '<>' ersetzt:

$ echo "a" | perl t.pl b c
b
$ARGV=b
c
$ARGV=c
a
$ARGV=-

*hrhrhr* Nein, ich versteh's grad auch nicht. Mit explitzitem '-' als
"Dateinamen" klappts aber:

$ echo "a" | perl t.pl b - c
b
$ARGV=b
a
$ARGV=-
c
$ARGV=c

Sowohl mit:

while(<>) { print; print STDERR "\$ARGV=$ARGV\n"; }

als auch

while(<ARGV>) { print; print STDERR "\$ARGV=$ARGV\n"; }

als einzigen Inhalt von 't.pl' (und beiden Zeilen! ;) ist:

$ echo "a" | perl t.pl b - c
b
$ARGV=b
a
$ARGV=-
c
$ARGV=c

die Ausgabe...

HTH,
-dnh
--
160: Webdesign
Irgendeinem nichtsahnenden Kunden Unsummen für die Gestaltung
seiner Internetpräsenz (siehe dort) abzuknöpfen. (Martin
Schmitt)
Christian Garbs
2020-12-15 19:10:42 UTC
Permalink
Mahlzeit!
Post by David Haller
Post by Christian Garbs
Hat da jemand einen Trick parat?
in="${1:--}"
foo "$in"
stellt zumindest mal shellcheck zufrieden, nur frisst längst nicht
jedes Programm auch "-" als "STDIN"-Platzhalter-Dateiname...
Exakt. (Oder gleich 'foo "${1:--}"', das spart das $in.)

Inzwischen habe ich nachgesehen: Das aufgerufene Skript ist zwar in
Perl geschrieben, der Autor (ich) verwendet aber while(<STDIN>).
Damit klappt dann nicht mal die Übergabe eines normalen Dateinamens
als Parameter.
Post by David Haller
An der Stelle würde ich shellcheck schlicht als überfordert ignorieren.
Ich will's aber hübsch haben ;-)

Eine "ShellCheck-konforme" Lösung haben wir ja jetzt gefunden.
Post by David Haller
Post by Christian Garbs
PS: Das ist ein Perlskript -- je nachdem, wie das implementiert ist,
könnte './anderes-skript.pl "${1:--}"' funktionieren. Ich wollte
das aber generell fragen, unabhängig von Perl ;-)
'while (<>)' ist mir geläufig, aber 'while (<ARGV>)' habe ich bisher
noch nie gesehen. Da werde ich nochmal in die Doku abtauchen.
Noch was dazugelernt!

Danke,
Christian
--
....Christian.Garbs....................................https://www.cgarbs.de
Freundliche Worte kosten nichts und bringen viel ein.
--Blaise Pascal
Lesen Sie weiter auf narkive:
Loading...