• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

in shellskript mit file überprüfen ,ob es Textdateiist[gelös

Code:
#! /bin/bash
#set -x

#realisiert wc Befehl


datzahler=0




             while true
              do

                b=		
                a=			
                c=

               echo " 1 für Anzahl der Zeichen "
               echo " 2 für ANzahl der Woerter "
               echo " 3 für Anzahl der Zeilen "

               echo -n " Was soll gezaehlt werden "
               read antwort



                  case  $antwort in 


                        1) echo "Welche datei soll gezeahlt werden"
                        echo "Bitte Datei eingeben"
                        read name1

                        a=$( file -i  $name1 | grep '^{*.}\.txt$' $name1 )



                      if [ -n  $a ]

                      then
                      zeichen=`cat $name1 | wc -c`
                      echo "Die Anzahl der Zeichen in Datei $name1 betreagt :$zeichen"

                      else

                    echo "Ist keine Textdatei"
                    let datzahler=$datzahler+1
                    echo "Es wurden $datzahler Dateien gezeahlt"
                    exit
 
                   fi;;

                             2) echo "Welche Datei soll gezeahlt werden?"
                             echo "Bitte Datei eingeben"
                             read name2
                             b=$( file -i  $name2 | grep '^{*.}\.txt$' $name2 )
                             if [ -n $b ]
	                     then
	                    woerter=`cat $name | wc -w`
	                    echo "Die Anzahl der Woerter betreagt : $woerter"

	                     else
	                   echo "Es ist keine Textdatei"
	                   let datzahler=$datzahler+1
	                   echo "Es wurden $datzahler Dateien gezeahlt"

                          fi;;



                                   3) echo "Welche Datei soll gezeahlt werden?"
                                   echo "Bitte eingeben"
                                   read name3
                                   c=$( file -i  $name3 | grep '^{*.}\.txt$' $name3 )
                                   if [ -n  $c ]
	                          then
      
                                  zeilen=` cat $name3 | wc -l`
                                  echo "Es wurden $zeilen Zeilen in Datei $name3 gezaehlt"
       

                                 else
                                  echo "Es ist keine datei"
                                  let datzahler= $datzahler+1
                                  echo "Es wurden $datzahler gezaehlt"

                                fi;;

*) echo "Skript wird beendet" 
exit;; 



esac

done
Habe es etzt umgeschireben, aber er zählt mir trotzdem die Wörter ,auch wenn es eine C-Datei ist
 
A

Anonymous

Gast
intergo schrieb:
Ok ,also ich hab jetzt es mit dem file -i versucht ,dich mein problem ist zu programmieren,d.h. wie sage ich in der if abfrage, dass wenn es keine Textdatei sit, dass er nicht zählen muss.?

So hier bestimmt nicht
Code:
  a=$( file -i  $name1 | grep '^{*.}\.txt$' $name1 )
if [ -n  $a ]
...........

Überlege mal was du da versuchst.
Du willst einer Variable a die Standard-Ausgabe folgender Befehlskette zuweisen
Code:
file -i  $name1 | grep '^{*.}\.txt$' $name1
Diese Befehlskette besteht als erstes aus dem Befehl
Code:
file -i  $name1
der in etwa folgende Ausgabe erzeugen könnte. /etc/fstab als Versuchskaninchen.
"/etc/fstab: text/plain; charset=us-ascii"
Diese Ausgabe schickst du über eine Pipe zu einem Grep
Code:
grep '^{*.}\.txt$' $name1
Dieses grep sucht nach "was ist erstmal egal" in der Datei, in unserem Beispielfall währe es dann die /etc/fstab
Es ließt überhaupt nicht aus der Pipe und macht darauf hin entweder eine entsprechend des Suchstrings eine doch ehr zufällige Ausgabe meistens jedoch gar keine Ausgabe die dann in der Variable a abgelegt wird. Nur wenn "was ist erstmal egal" in der Datei stehen würde, würde eine Ausgabe machen die auch in a abgespeichert wird.
Dein if prüft also einen absolut zufälligen Wert und wird meist den then-Zweig durchlaufen, da a meistens leer bleibt.


robi schrieb:
Dann nimm mein letztes Beispiel und füge dort ein paar kleine Änderungen ein.
warum hörst du nicht auf solche Ratschläge und willst die Welt neu erfinden. :schockiert:

Code:
if file -N  DATEI |  cut -d: -f2  | grep "text" >/dev/null ; then  echo  "ist text"; else  echo "kein text"; fi
oder auseinander genommen
Code:
if file -N  DATEI |  cut -d: -f2  | grep "text" >/dev/null 
     then 
            echo  "ist text"
     else  
            echo "kein text"
 fi

nach 5 Minuten und ein paar kleinen Änderungen und Erweiterungen wird daraus zB
Code:
if file -N  "$DATEI" |  cut -d: -f2  | grep "text" >/dev/null 
     then 
            echo  "$DATEI ist eine  textdatei "
            BYTE=$(wc -c "$DATEI" | cut -d " " -f1 )
            ZEILEN=$(wc -l "$DATEI" | cut -d " " -f1 )
            WORTE=$(wc -w "$DATEI" | cut -d " " -f1 )
            echo "$DATEI hat $ZEILEN Zeilen ; $WORTE worte und ist $BYTE Zeichen lang."
     else  
            echo "$DATEI kein textdatei und nicht geeignet zur Untersucheung durch den Befehl wc"
 fi
und schon hast du das halbe Script. Jetzt brauchst du nur noch zu schauen und zu überlegen warum die einzelnen Befehle so aussehen und ein bischen damit rumspielen damit du erkennst was da im einzelnen genau passiert. Wenn du das einigermaßen verstanden hast, dann nur noch die Eingaben programmieren und aus der einen echo-Ausgabe im then-Zeig einfach noch einen switch einbauen, in dem du dann auf die verschiedenen Anforderungen hin die verschiedenen echo-Ausgabe machst die du gerne haben willst, und fertig.

robi
 
ok , du hast recht, ich will halt auch mal selbst drauf kommen , bevor ich etwas anderes übernehme ,weil ich immer ziemlich ehrgezizig bin.
Aber danke für den tipp, ich sollte versuchen, mal das was du mir da geschrieben hast zu verstehen, denn so lernt man auch.
Sag mla, wie hast du das Shellskript schreiben so gut gelernt?

Ihr seid echt profis!!!
Tolles forum
Ich werd es mal versuchen zu verstehen, und werde dir bescheid geben.
Danke
 
A

Anonymous

Gast
intergo schrieb:
Sag mla, wie hast du das Shellskript schreiben so gut gelernt?
Ganz einfach, ich hab mich 18 Jahre tag-täglich beruflich und privat damit beschäftigt.
Also nicht verzweifeln wenn's mal nicht in 5 Minuten funktioniert. ;)

robi
 
HI robi, mir ist noch ne andere möglichkeit vielleicht eingefallen , die funktionieren könnte, doch noch nicht ausprobiert ,da ich in der vorlesung war und zwar.

file Datei >>test.txt
a=`grep "text" test.txt`

und dann würde ich es in der if abfrage reinpasteln:

und zwar if [ $a true ]
then

Befehl zum zählen der Zeichen

else

exit
 
Hi,

das geht auch. Du kannst das sogar abkürzen.

Code:
a=`file Datei | grep "text"`

Das hängt immer vom Fall und der (erträglichen) Komplexität des Scriptes ab.

Gruß
Georg
 
wie meinst du das mit der komplexität?

also das ist mein code , ohne dem genantnen befehl:
Code:
#! /bin/bash
#set -x

#realisiert wc Befehl


datzahler=0

while true
do




echo " 1 für Anzahl der Zeichen "
echo " 2 für ANzahl der Woerter "
echo " 3 für Anzahl der Zeilen "

echo -n " Was soll gezaehlt werden "
read antwort



case $antwort in


1) echo "Welche datei soll gezeahlt werden"
echo "Bitte Datei eingeben"
read name1
file $name1
if ( test find . -name "*.txt" )

then
zeichen=`cat $name1 | wc -c`
echo "Die Anzahl der Zeichen in Datei $name1 betreagt :$zeichen"

else

echo "Ist keine Textdatei"
let datzahler=$datzahler+1
echo "Es wurden $datzahler Dateien gezeahlt"
exit

fi;;

2) echo "Welche Datei soll gezeahlt werden?"
echo "Bitte Datei eingeben"
read name2
file $name2
if [ -f $name2 ]
then
woerter=`cat $name | wc -w`
echo "Die Anzahl der Woerter betreagt : $woerter"

else
echo "Es ist keine Textdatei"
let datzahler=$datzahler+1
echo "Es wurden $datzahler Dateien gezeahlt"

fi;;



3) echo "Welche Datei soll gezeahlt werden?"
echo "Bitte eingeben"
read name3
file -i $name3
if [ -f $name3 ]
then
zeilen=` cat $name3 | wc -l`
echo "Es wurden $zeilen Zeilen in Datei $name3 gezaehlt"


else
echo "Es ist keine datei"
let datzahler= $datzahler+1
echo "Es wurden $datzahler gezaehlt"



fi;;

*) echo "Skript wird beendet"
exit;;



esac

done
müsstee eignetlich auch gehen
 
Naja, wenn man zuviele Kommandos in einer Zeile verkettet wird das schnell unübersichtlich bis grauslig.
Mitunter hatte ich schon Probleme die notwendigen Anführungzeichen ineinander zu verschachteln.
Dann muss man zusehen, dass man es auf mehrere Zeilen verteilt und hilfsweise in Dateien schreibt.

Gruß
Georg
 
A

Anonymous

Gast
intergo schrieb:
file Datei >>test.txt
a=`grep "text" test.txt`

hat 2 Schönheitsfehler, der erste ist sehr leicht behoben. Und zwar schreibst du immer weiter in die selbe Datei am Ende weiter. Das bedeutet, hast du einmal eine Textdatei bearbeitet, werden alle weiteren Dateien ob Textdatei oder nicht auch als Textdatei gewertet. Da grep in der Datei immer diesen Eintrag findet.

der 2. Schönheitsfehler ist folgender, was passiert denn wenn deine Datei "textdatei.tar.gz" heisen sollte und keine Textdatei ist sondern ein komprimiertes Archiv. Da du die gesamte Ausgabezeile von file auswertest, suchst du mit grep dann auch im Dateinamen mit und wirst fündig wenn der Dateiname "text" enthält.

Noch eine kurze Bemerkung zu deinen Scripten. Versuche dich in die Situation zu versetzten in der du bist. wenn du nach 3 Monaten deine Script wieder öffnest. Wenn du das Script gut geschrieben hast, dann wirst du schnell erkennen was das Script macht und was da vor sich geht, und kannst dann auch schnell Änderungen und Ergänzungen vornehmen. Ein schlecht geschriebenes Script kannst du in 3 Monaten nur mit dem selben Aufwand verstehen, den du für das Neuschreiben auch benötigen würdest. ;) ;) ;)

Desweiteren bin ich mir gar nicht so sicher ob du deine eigenen Scripte überhaupt auch mal ausprobierst.
Code:
if ( test find . -name "*.txt" )
ist Schrott und erzeugt nur die Fehlermeldung "-bash: test: too many arguments" das hatte ich schon einige Beiträge weiter vorne mal vermerkt.

Irgendwie hat man wiedermal vergessen euch zu erzählen wie "if" wirklich funktioniert und das "test" auch nur ein Kommando ist das Argumente verarbeitet und das auch noch sehr streng.
Code:
 if list; then list; [ elif list; then list; ] ... [ else list; ] fi
deine "if-Kommando-Liste" ist "test file" und bedeutet du untersuchst ob die Länge des Strings "file" nicht 0 ist, was sie niemals sein kann, und anschließend kommen für das Kommando "test" noch weitere Zeichen die das Kommando "test" überhaupt nicht versteht ". -n...........". Schon bei dem Punkt steigt "test" aus und bringt die obrige Fehlermeldung.
Die Fehlermeldung ist nicht besonders schön und irreführend, das liegt daran da es zwei verschieden "test" Kommandos gibt, Das welches du verwendest ist ein eingebautes in der Shell. Nimm mal das richtige "test" Programm in dem du "/usr/bin/test" schreibst, und du wirst oftmals bessere Fehleranzeigen bekommen die leichter zu verstehen sind.

robi
 
Da hast du recht , ich muss es mir mit den Einrückungen angewöhnen und das mit dem text hatte mich verschrieben.
Zu dem 2. Schönheitsfehler hatte ich jetzt nicht daran gedacht , aber wenn file als ausgabe text ausgibt hätte ich doch das problem gar nicht oder täusche ich mich?

DDanke für deine Wertvollen tipps
 
Ich probiere meine Skripte immer aus, denn sonst bräuchte ich sie gar nicht zu schreiben und damit auch Zeit zu verscwenden.
Ich will es halt lernen , weil ich es muss und weil mich es interessiert deshlab probiere ich halt viel aus , um die funktionosweise zu verstehen.
 
Sorry robi, das mit den 2 verschiedenen Testkommandos verstehe ich nicht?

mit /usr /bin/test
wie wende ich es an?
 
RObi, hätte ne frage kann man die if Abfrage , die du mir vorgeschalgen hast:

ile -N "$name1" | cut -d: -f2 | grep "text" >/dev/null

auch leichter gesalten, bzw. ohne dieses cut, bzw einfach nur in datei umlenkne und von der Datei es ablesen bzw.

file $Datei >>test.txt | echo $Datei | grep "text". müsste doch eigentich das gleiche sein, nur er macht dann die Abfrage wieder nicht richtig,Mit deinem Code macht er es richtig.

Was mache ich da falsch
 
Sorry robi, hab das nochmal mit dem cut -d: -f2 ir angeschaut
Ich weiß das das f2 für das zweite feld in der lste ist, warum geht es nicht, wenn ich f3 oder f4 sage anstatt f2, denn dann funtioniert deine vorgeschlagene if-aneisung nicht.
Das verstehe ich nicht
Tut mir leid für das ständige fragen
 
Oh Mann ist das ein Durcheinander hier!

intergo, achte mal bitte auf Deine Rechtschreibung, auch im Skript! "2 für ANzahl", "Die Anzahl der Woerter betreagt" usw., das geht gar nicht.
-------------------------------------------------
Eigentlich geht es ja hier um das Testen von Dateien mit 'file'.
Da gibt es zwei Arten von Dateien, binäre Dateien und Textdateien.
Unter Linux soll die Unterscheidung eigentlich gar nicht so wesentlich sein (siehe z.B. 'perldoc -f binmode', dazu 'perldoc -f open':
Systems like Unix, Mac OS, and Plan 9, which delimit lines with a single character, and which encode that character in C as "\n", do not need "binmode". The rest need it.
).
Im Prinzip werden in beiden Arten von Dateien Daten byteweise gespeichert.
Textdateien werden wohl typischerweise überwiegend Bytes enthalten, die im Zeichensatz Textzeichen zugeordnet sind (ferner '\n').
Ich denke, im Prinzip gibt es keine wirklich sichere Möglichkeit, eine Textdatei daraufhin zu überprüfen, ob sie C-Code oder sprachlichen Text enthält. Na gut, man könnte versuchen, sie zu kompilieren, und wenn das ohne Fehler durchläuft, wird es wohl C-Code gewesen sein. ;)
Aber sonst ist die Prüfung doch etwas unsicher. Deshalb ist da wohl auch von 'Magic' die Rede, siehe auch 'man magic' zu der Magie des 'file'-Befehls.
Normalerweise verwendet man in der Programmierung ja lieber harte Mathematik und Algorithmen. Deshalb fand ich "Magic" in diesem Zusammenhang eigentlich recht lustig.

Viele Grüße
 
A

Anonymous

Gast
if und danach kommt eine Kommando oder auch mehrere Kommandos

also zB
Code:
if cat Datei | grep auto
Der Befehl oder die Befehlsgruppe ist hier im Beispiel "cat Datei | grep auto" und der letzte Befehl wird einen Rückgabewert haben, der entweder "0" ist wenn das letzte Kommando erfolgreich war, oder nicht "0" wenn er nicht erfolgreich war. Bei "grep" wird immer "0" zurückgegeben wenn mindestens ein Eintrag gefunden wurde.
fast jedes Kommando wird in Linux bei Erfolg eine "0" zurückgeben. Dieser Wert vom letzten aufgerufenen Befehl wird ansonsten immer in der Bash in der Variable "?" gespeichert und du könntest ihn dann auch mit
Code:
echo $?
auslesen.

Diesen Rückgabewert, den verwendet jetzt auch "if" und zwar bei "0" für den Durchlauf des THEN-Zweig.

Bei "if" kannst du viele Befehle und auch ganze Befehlsketten verwenden.
"test" ist nur eine kleines Programm für ein paar sehr oft benötigte Tests, von Strings, Integer und Dateien.
Aber es ist ein ganz normales Programm und genau so verhält es sich auch.
Code:
# ls -l /usr/bin/test
-rwxr-xr-x. 1 root root 34384  3. Nov 12:42 /usr/bin/test
und damit nicht genug. Es gibt das Kommando "test" auch noch mehrfach einmal sogar als Eckige Klammer als Dateiname ;)
Das Programm "/usr/bin/[" ist auch weiter nichts als das Programm "/usr/bin/test" in einigen Distributionen ist es sogar ein Hardlink auf die selbe Datei. (aber nicht in jedem Linux ist beides wirklich gleich kompiliert. stammt aber aus dem selbem Quellcodedateien)
Und genau aus diesem Grund muss hinter der "[" und vor der "]" auch immer ein Leerzeichen steht, eben weil das erste ein Dateiname ist und das zweite eine spezielle Option die einfach nur ignoriert wird und als Ende der Optionskette gewertet wird.

Und es gibt noch eine Variante von "test", und zwar ein Shellbuildin, also ein "test" Programm das mit den selben Optionen arbeitet und sich genau so verhält, das aber schon fest in der Bash integriert ist. Dieses hat den Vorteil das es schneller ist, da nicht erst ein weiteres Programm extra gestartet werden muss.

es ist also mehr oder weniger vollkommen egal ob du schreibst
Code:
if test -n $VAR
if [ -n $VAR ]
if /usr/bin/test -n $VAR
du verwendest dabei aber unterschiedliche "test" Kommandos ohne das du es wirklich merkst.

Aber du benötigst nicht unbedingt "test", hinter einem "if" . Und auch nicht unbedingt eine Runde Klammer,( die Erklärung dazu verkneife ich mir mal, sonst wird's noch unübersichtlicher für dich)
HInter "if" könnte auch jeder andere Befehl stehen. Wenn dort aber "test" steht dann sollten auch die Optionen dieses Programmes richtig dort stehen und nicht irgendwelche andere Kommandos die dort nichts zu suchen haben. Dazu die Manpage von "test" lesen.

Na ich hoffe mal, jetzt habe ich dich noch komplett verwirrt. ;) ;) ;) ;)

du kannst auch das "cut" weglassen, dann darf nur in deinem Dateinamen nicht "test" vorkommen, sonst könnte dein Script Fehler machen.
Code:
file $DATEI| grep text > /dev/null]
das ">/dev/null" ist dort nur, damit er die Ausgabe des "grep" in den Mülleimer wirft, wir brauchen für "if" nur den Rückgabewert von "grep" und nicht die Ausgabe. Wenn du willst kannst du das auch noch weglassen, du musst nur den Überblick behalten welches Kommando jetzt welche Ausgabe macht.

robi

@abgdf
"Oh Mann ist das ein Durcheinander hier!"
hab ich ein Glück dass ich hier im Unterforum nicht für das Aufräumen zuständig bin. ;) robi
 

framp

Moderator
Teammitglied
abgdf schrieb:
robi, Du bist einfach zu nett. Bald hast Du ihm die ganze bash erklärt. :p
Wenn das hier so noch ein wenig weitergeht kann man aus dem Inhalt des Threads ein robi's bash crash Kurs Booklet erstellen :D
 
Oben