Paddy_123
Anmeldungsdatum: 19. Juli 2020
Beiträge: 27
|
Hallo liebes Forum,
ich versuche mich gerade in scripting einzuarbeiten und hätte gerne Feedback zu meinem "ersten" kleinen Script Mein Script ist eine einfache Suche nach File oder Directory mit kleinem Menü das mir entweder die File anzeigt oder direkt ins Verzeichnis wechselt.
Es beschränkt sich zunächst nur aufs Homeverzeichnis und ich starte es mit:
source ./script Mir geht es vor allem um Feedback hinsichtlich der Übersichtlichkeit, ist es verständlich für andere? Kann ich es effizienter / besser gestalten / kürzer: Vielen Dank, hier mein Script 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 | #!usr/bin/zsh
echo "Was suchst du?"
echo "1 File"
echo "2 Directory"
echo "3 Abbrechen"
echo "Gib bitte eine Zahl ein :) "
read n
if [[ $n -eq 1 ]]
then
echo "Welche file suchst du?"
read f #Eingabe welche File gesucht wird
echo "Möchtest du ins Verzeichnis wechseln?"
echo "1 JA"
echo "2 NEIN"
read antwort #ins Directory wechseln ja/nein?
f1=$( find ~/ -type f -iname $f )
f2=$( dirname $f1 )
if [[ $antwort -eq 1 ]] then
cd $f2 #wechselt ins Diretory
elif then
echo $f1 #gibt File aus
fi
elif [[ $n -eq 2 ]] then
echo "Welches Directory suchst du?"
read d
echo "Möchtest du ins Directory wechseln?"
echo "1 Ja"
echo "2 NEIN"
read antwort
d1=$( find ~/ -type d -iname $d )
if [[ $antwort -eq 1 ]] then
cd $d1
elif then
echo $d1
fi
elif [[ $n -eq 3 ]] then
echo "Programm abgebochen, einen schönen Tag noch."
else
echo "Fehler in der Eingabe"
fi
|
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12801
|
Du hast das grundsätzliche Problem, dass ein cd in Deinem Skript keine Auswirkungen auf die aufrufende Shell hat, zu der Du ja zurückkehrst sobald das Skript beendet ist. So etwas bekommt man elegant nur mit einer Shell-Funktion hin, die in der ~/.bashrc oder ~/.bash_aliases definiert wird. Ganz allgemein finde ich "Datei / Ordner Suchen" und "In Verzeichnis wechseln" verschieden genug, dass ich sie nicht in einem Skript abhandeln würde. Dann kannst Du nämlich auch das unten genannte Problem mit mehreren gefundenen Dateien leichter handhaben (z.B. indem Du nach der Ausgabe des ersten Treffers find beenden lässt). Du hast da einiges an redundantem Code in den beiden Zweigen für "Datei" und "Ordner". Das könnte man elegant zusammenfassen, indem man z.B. den gesuchten Dateityp in einer Variable ablegt, die dann hinter find -type verwendet wird. Dann hast Du ein Problem, wenn mehrere Dateien des angegebenen Namens gefunden werden. Dann sehen $f2 und $f2 (nicht sehr sprechende Namen übrigens) nicht so aus, wie Du vielleicht möchtest. Insbesondere wird dann der cd mehr als ein Argument sehen und sich beschweren. Ich persönlich bin kein großer Fan von interaktiven Skripten. Man hat ja schon die interaktive Shell und kann dann da auch Parameter an ein Skript übergeben.
|
Paddy_123
(Themenstarter)
Anmeldungsdatum: 19. Juli 2020
Beiträge: 27
|
Ich hab es nochmal durchgetestet und es war ziemlich unbefriedigend. Hat nur "unicative Dateien" gefunden und ins Verzeichnis gewechselt. Bei Mehrfachausgabe wusstes es nicht nicht in welches Verzeichnis gewechselt werden soll.
Ich habe versucht mit
find ~/ -type f -iname $1 | nl | grep $2
zu pipen. Ich könnte dann auch z.B NR 2 auswählen und ausgeben, allerdings weiß ich nicht wie ich die 2 wieder entferne um sie ins cd-Command zu schmeißen. Weiter habe ich noch mit | wc -l eine weitere If-Abfrage eingebaut. Wenn ich mehrere Treffer habe kommt eine weitere Abfrage. Hier der erweiterte Code; Das ganze Ding sollte man doch mit functions wesentlich übersichtlicher hinebkommen oder? Vielen Dank Pad // Ach ja so richtig getestet hab ich die Version noch nicht, hab kein Nerv mehr heute dafür ☺ 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 | #!/usr/bin/zsh
#Suchprogramm für Files oder Directories mit der Option in diese zu wechseln.
#
#Intro Menu
echo "Was suchst du?"
echo "1 File"
echo "2 Directory"
echo "3 Abbrechen"
echo "Gib bitte eine Zahl ein :) "
read n
#Filesuche
if [[ $n -eq 1 ]]
then
echo "Welche file suchst du?"
read f #Eingabe welche File gesucht wird
echo "Möchtest du ins Verzeichnis wechseln?"
echo "1 JA"
echo "2 NEIN"
read antwort #ins Directory wechseln ja/nein?
#Var definitionen
f1=$( find ~/ -type f -iname $f )
f2=$( dirname $f3 )
f4=$( dirname $f )
if [[ $antwort -eq 1 ]] then
#WC filtert die Anzahl der Ergebnisse heraus
wc=$( find ~/ -type f -iname $f | wc -l )
#Wenn mehrere Suchtreffer dann wird mit grep eingeschränkt.
if [[ wc -gt 1 ]] then
echo $f1
echo "In welchem Ordner soll ich suchen? Bitte etwas unicatives" #falls es mehrere Optionen gibt
read x
f3=$( find ~/ -type f -iname $f | grep $x )
cd $f2
#Wenn nur ein Treffer kann direkt ins Verzeichnis gewechselt werden
elif cd $f4
fi
#Oder Ordnerwechsel ist nicht gewünscht und Suchergebnis wird asugegeben
elif then
echo $f1 #gibt File aus
fi
# Suche nach Directories
elif [[ $n -eq 2 ]] then
echo "Welches Directory suchst du?"
read d
echo "Möchtest du ins Directory wechseln?"
echo "1 Ja"
echo "2 NEIN"
read antwort
d1=$( find ~/ -type d -iname $d )
if [[ $antwort -eq 1 ]] then
#WC Suche wie bei Files
wc=$( find ~/ -type d -iname $d | wc -l )
if [[ $wc -gt 1 ]] then
echo $d1
echo "In welchem Ordner soll ich suchen? Gib etwas unicatives ein" #falls es mehrere Optionen gibt
read x
d2=$( find ~/ -type d -iname $d | grep $x )
cd $d2
elif
cd $d1
fi
#Wenn kein Verzeichniswechsel gewünscht dann Ausgabe
elif then
echo $d1
fi
#Option 3 // Programmabbruch oder falsche Eingabe
elif [[ $n -eq 3 ]] then
echo "Programm abgebochen, einen schönen Tag noch."
else
echo "Fehler in der Eingabe"
fi
|
|
Paddy_123
(Themenstarter)
Anmeldungsdatum: 19. Juli 2020
Beiträge: 27
|
rklm schrieb: Du hast das grundsätzliche Problem, dass ein cd in Deinem Skript keine Auswirkungen auf die aufrufende Shell hat, zu der Du ja zurückkehrst sobald das Skript beendet ist. So etwas bekommt man elegant nur mit einer Shell-Funktion hin, die in der ~/.bashrc oder ~/.bash_aliases definiert wird.
Wenn ich es im Terminal mit "source ./script" öffne wird es ausgeführt ohne Probleme auch der cd-Befehl funktioniert. Ohne "source" ist es richtig
Ganz allgemein finde ich "Datei / Ordner Suchen" und "In Verzeichnis wechseln" verschieden genug, dass ich sie nicht in einem Skript abhandeln würde. Dann kannst Du nämlich auch das unten genannte Problem mit mehreren gefundenen Dateien leichter handhaben (z.B. indem Du nach der Ausgabe des ersten Treffers find beenden lässt).
Ob das Programm notwendig oder sinnvoll ist bezweifel ich ebenfalls ☺. Ein Menu macht es träge.
Mir ging es aber mehr darum mit ifs und variablen zu arbeiten. Mit dem find-Befehl bekomm ich ein Ergebnis und sehe wie weit ich noch entfern bin ☺
Du hast da einiges an redundantem Code in den beiden Zweigen für "Datei" und "Ordner". Das könnte man elegant zusammenfassen, indem man z.B. den gesuchten Dateityp in einer Variable ablegt, die dann hinter find -type verwendet wird.
Wie meinst du das mit zusammenfassen? Die Frage ist ob der Typ überhaupt notwendig ist ... mit iname kann ich ja grundsätzlich nach beidem suchen. Aber auch hier ging es mir mehr ums Menu und verschachtelte ifs und oder andere Vorschläge
Dann hast Du ein Problem, wenn mehrere Dateien des angegebenen Namens gefunden werden. Dann sehen $f2 und $f2 (nicht sehr sprechende Namen übrigens) nicht so aus, wie Du vielleicht möchtest. Insbesondere wird dann der cd mehr als ein Argument sehen und sich beschweren.
Das habe ich auch festgestellt und noch was dran gehängt um bei Mehrfachausgabe nochmals zu diffenzieren.
Das $f nicht ansprechend ist habe ich im selben Zug gemerkt ... als ich bei den wenigen Zeilen schon leicht durcheinander gekommen bin. Danke fürs Feedback und die Zeit 😉
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12801
|
Paddy_123 schrieb:
// Ach ja so richtig getestet hab ich die Version noch nicht, hab kein Nerv mehr heute dafür ☺
In Zeile 23 ist f3 nicht definiert. So könnte man das auch machen: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | d() {
case "$1" in
file) type=f;;
dir) type=d;;
*) echo "ERROR: command is 'file' or 'dir'"; return 1;;
esac
case "$2" in
cd) found="$(find -type $type -iname "$3" -print -quit)"
if [ -d "$found" ]; then
cd "$found"
else
cd "$(dirname "$found")"
fi;;
show) find -type $type -iname "$3";;
*) echo "ERROR: operation is either 'cd' or 'show'"; return 2;;
esac
}
|
|
Paddy_123
(Themenstarter)
Anmeldungsdatum: 19. Juli 2020
Beiträge: 27
|
In Zeile 23 ist f3 nicht definiert.
Ich hab es in Zeile 33 definiert. Führt das zu einem Fehler? Deine Version sieht deutlich angenehmer aus und leuchte mir denke ich so weit auch ein (ich schau es mir morgen mal genauer an). Nur eine Sache versteh ich nicht. else
cd "$(dirname "$found")"
fi;;
Warum hast du hier 2 ";;" gesetzt? Reicht "fi" nicht aus? Oder hat das was mit case zu tun? Danke dir für deine Mühe.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12801
|
Paddy_123 schrieb: In Zeile 23 ist f3 nicht definiert.
Ich hab es in Zeile 33 definiert. Führt das zu einem Fehler?
Klar: | $ dirname $leer
dirname: missing operand
Try 'dirname --help' for more information.
$ dirname
dirname: missing operand
Try 'dirname --help' for more information.
|
Deine Version sieht deutlich angenehmer aus und leuchte mir denke ich so weit auch ein (ich schau es mir morgen mal genauer an). Nur eine Sache versteh ich nicht. else
cd "$(dirname "$found")"
fi;;
Warum hast du hier 2 ";;" gesetzt? Reicht "fi" nicht aus? Oder hat das was mit case zu tun?
Letzteres. Die zwei Semikolons beenden einen Fall vom case . Mir fällt noch auf, ich habe vergessen die Fehlermeldungen nach Stderr umzuleiten. Also z.B. in Zeile 5 sollte es dann so aussehen: | *) echo "ERROR: command is 'file' or 'dir'" >&2; return 1;;
|
Danke dir für deine Mühe.
Bitte!
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
Die Bash kennt den praktischen select-Befehl: | select datei in $(find . -type f -name ....)
do
# mach was mit $datei
done
|
Hat die zsh sowas nicht?
|
Paddy_123
(Themenstarter)
Anmeldungsdatum: 19. Juli 2020
Beiträge: 27
|
user_unknown schrieb: Die Bash kennt den praktischen select-Befehl: | select datei in $(find . -type f -name ....)
do
# mach was mit $datei
done
|
Hat die zsh sowas nicht?
Doch hat sie, kannte ich aber bisher noch nicht. Werd ich auch mal mit rumspielen. Ich hab das ganze Teil jetzt nochmal mit case ausporbiert, es ist kürzer läuft aber noch nicht ..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 | #!/usr/bin/zsh
#Programm um File oder Directory zu suchen, auszugeben oder ins Directory zu wechseln.
#
#Abfrage f or d
echo "Was suchst du?"
echo "1=File"
echo "2=Directory"
read fileordirectory
#Abfrage Suche
echo "Gib deine Suche ein!"
read suche
#Abfrage show of change
echo "Möchtest du deine Suche anzeigen oder wechseln?"
echo "1=wechseln"
echo "2=anzeigen"
read showorchange
#File or Dir case
case $fileordirectory in
1) type=f;;
2) type=d;;
*) echo "Error existiert nicht" >&2; return 1;;
esac
#Suche
case $showorchange in
1)morethan1=$(find /home/$(whoami)/ -type $type -iname $suche | wc -l)
#Wenn mehr als ein Suchergebnis existiert mit wc -l Zeilen zählen
if [ $morethan1 -gt 1 ]; then
find /home/$(whoami)/ -type $type -iname $suche | nl
echo "Welches Ergebnis möchtest du?"
read x
# head + tail = x
let headtail=$morethan1-$x
if [ $fileordirectory -eq 2 ]; then
cd $(find /home/$(whoami)/ -type $type -iname $suche | head -n$x | tail -n$headtail)
else
cd $(dirname $(find /home/$(whoami)/ -type $type -iname $suche | head -n$x | tail -n$headtail))
fi
else [ $morethan1 -eq 1 ]; then
found1=$(find /home/$(whoami)/ -type $type -iname $suche)
if [ $fileordirectory -eq 2 ]; then
cd $found1
else
cd $(dirname $found1)
fi
fi;;
2) find /home/$(whoami)/ -type $type -iname $suche;;
*) echo "Nichts gefunden"; return 2;;
esac
|
Ich bekomme folgenden Fehler:
| ./casetest.sh:42: parse error near `then'
|
2 Fragen hierzu:
1. im Fehlerprotokoll zählt er die Kommentare nicht mit. Ich behelfe mir indem ich die Datei mit 'cat "script" | nl ' anzeigen lasse.
Ich arbeite mit VIM kann man hier die Kommentare irgendwie ausblenden bzw wie finde ich in VIM Zeile 42 ... was im VIM eigentlich Zeile 44 wäre. 2. Wenn ich bei der Abfrage 1 für File, dann die File und bei "Suchen oder Anzeigen" 2 eingebe. Sollte er doch eigentlich Case 1 "Anzeigen" überspringen/auslassen.
Hier zeigt er mir aber auch den Fehler an.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
Ich habe die ZSH nie benutzt, daher eine wüste Spekulation: | else [ $morethan1 -eq 1 ]; then
|
In der Bash müsste das Schlüsselwort elif heißen, wenn danach eine weitere Bedingung kommt. In anderen Sprachen benutzt man einfach ein neues if nach else .
|
Paddy_123
(Themenstarter)
Anmeldungsdatum: 19. Juli 2020
Beiträge: 27
|
user_unknown schrieb: Ich habe die ZSH nie benutzt, daher eine wüste Spekulation: | else [ $morethan1 -eq 1 ]; then
|
In der Bash müsste das Schlüsselwort elif heißen, wenn danach eine weitere Bedingung kommt. In anderen Sprachen benutzt man einfach ein neues if nach else .
Benutzt man nicht immer if / elif / else? In Zeile 30 mach die IF auf und dann kommt nur else 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | if [ $morethan1 -gt 1 ]; then
find /home/$(whoami)/ -type $type -iname $suche | nl
echo "Welches Ergebnis möchtest du?"
read x
# head + tail = x
let headtail=$morethan1-$x
----------------------------------
else [ $morethan1 -eq 1 ]; then
found1=$(find /home/$(whoami)/ -type $type -iname $suche)
if [ $fileordirectory -eq 2 ]; then
cd $found1
else
cd $(dirname $found1)
fi
fi;;
|
Oder versteh ich da was falsch? Danke dir
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
Ich habe Zeile 40 zitiert, da steht ein | else BEDINGUNG ; then ...
|
Aber üblicherweise folgt einem else keine Bedingung. | if (( 3 > 4 ))
then
echo nanana
else
echo nun ja
fi
|
Drei ist größer als 4 oder auch nicht. Eine weitere Bedingung erzwingt in den meisten Sprachen ein verschachteltes, neues if:
| if (( 3 > 4 ))
then
echo nanana
else
if (( 3 == 4 ))
then
echo kaum besser
else
echo ja
fi
fi
|
wobei die Bash das Schlüsselwort **elif** anbietet:
| if (( 3 > 4 ))
then
echo nanana
elif (( 3 == 4 ))
then
echo kaum besser
else
echo ja
fi
|
Was die Zsh macht, weiß ich nicht.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12801
|
user_unknown schrieb:
wobei die Bash das Schlüsselwort **elif** anbietet:
Das ist sogar POSIX-Standard.
| if (( 3 > 4 ))
then
echo nanana
elif (( 3 == 4 ))
then
echo kaum besser
else
echo ja
fi
|
Was die Zsh macht, weiß ich nicht.
Das gleiche.
|