ubuntuusers.de

"read -s -n 1" in einem shellscript

Status: Gelöst | Ubuntu-Version: Kubuntu 11.10 (Oneiric Ocelot)
Antworten |

Kalter_Stern

Avatar von Kalter_Stern

Anmeldungsdatum:
12. Juni 2009

Beiträge: 218

Salute,

ich habe zwei verschiedene shell-scripte, das eine ersetzt global die (m.E. ziemlich hässlichen) Amarok-Icons, das andere für verschiedene "Aufräumoptionen" durch. In beiden möchte ich eine Operation nur durchführen, wenn der User sie erlaubt, dabei kommt es zu einer Fehlermeldung.

Im "Amarok"-Script funktioniert dieser aufrauf:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
echo -e $RED"Wollen sie das Arbeitsverzeichnis $(pwd) löschen? (y/n)"$ENDCOLOR

read -s -n 1 INPUT

case ${INPUT} in
        [yYjJ] )
                echo "Das Verzeichnis $(pwd) wird rekursiv gelöscht"
		rm -r $(pwd)
		sleep 2
;;
        * )
                echo "Verzeichnis $(pwd) wird nicht gelöscht"
		sleep 2

    # clear
        ;;
esac 

Im "ubucleaner" Script möchte ich, unter andere, die alten Kernel löschen:

1
CURKERNEL=$(uname -r|sed 's/-*[a-z]//g'|sed 's/-386//g')

und

1
OLDKERNELS=$(dpkg -l|awk '{print $2}'|grep -E $LINUXPKG |grep -vE $METALINUXPKG|grep -v $CURKERNEL)

Wenn ich in diesem Script den read aufrauf auch mit -s -n 1 mache:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
echo $BLUE"Purge old Kernel: $OLDKERNELS (current kernel:$CURKERNEL) (y/n)?"$ENDCOLOR

read -s -n 1 INPUT

case ${INPUT} in
        [yYjJ] )
                echo $BLUE"Removing old kernels..."$ENDCOLOR
		sudo apt-get purge $OLDKERNELS
		sleep 1
;;
        * )
                echo "Not doing anything"
		sleep 1

    # clear
        ;;
esac

erhalte ich den Hinweise

1
read: 24: Illegal option -n

- hat jemand eine Idee, woran das liegt? Wenn ich es ohne -s und -n 1 aufrufe funktioniert es (den Befehl habe ich aus dem amarok-script kopiert) ?

Vielen Dank,

KS

-edit-

ein ganz ähnliches Problem habe ich mit dem "echo", im amarok-script habe ich echo -e, im ubucleaner geht -e nicht. Kann das daran liegen, dass ich das eine script direkt aufrufe, das andere aber über einen alias in der .bashrc?

diesch Team-Icon

Avatar von diesch

Anmeldungsdatum:
18. Februar 2009

Beiträge: 5072

Wohnort: Brandenburg an der Havel

-s und -n sind Bash-spezifische Erweiterungen von read und funktionieren daher nur in Bash-Skripts, aber nicht in sh-Skripts.

Dein Skript muss daher

1
#!/bin/bash

als ersten Zeile haben.

Kalter_Stern

(Themenstarter)
Avatar von Kalter_Stern

Anmeldungsdatum:
12. Juni 2009

Beiträge: 218

Hm, sie haben beide als erste Zeile

1
#! /bin/bash

?

Das ganze script (in dem es nicht funktioniert) sieht so aus:

 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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#!/bin/bash

CURKERNEL=$(uname -r|sed 's/-*[a-z]//g'|sed 's/-386//g')
LINUXPKG="linux-(image|headers|ubuntu-modules|restricted-modules)"
METALINUXPKG="linux-(image|headers|restricted-modules)-(generic|i386|server|common|rt|xen)"
OLDKERNELS=$(dpkg -l|awk '{print $2}'|grep -E $LINUXPKG |grep -vE $METALINUXPKG|grep -v $CURKERNEL)
RED="\033[0;31m"
ENDCOLOR="\033[0m"
BLUE='\033[01;34m'

if [ $USER != root ]; then
  echo $RED"Error: must be root"
  echo "Exiting..."$ENDCOLOR
  exit 0
fi

clear

#echo $BLUE"current kernel: $CURKERNEL"$ENDCOLOR
sleep 1

echo $BLUE"Purge old Kernel: $OLDKERNELS (current kernel:$CURKERNEL) (y/n)?"$ENDCOLOR

read INPUT

case ${INPUT} in
        [yYjJ] )
                echo $BLUE"Removing old kernels..."$ENDCOLOR
		sudo apt-get purge $OLDKERNELS
		sleep 1
;;
        * )
                echo "Not doing anything"
		sleep 1

    # clear
        ;;
esac


echo $BLUE"updating the package cache and checking for broken dependencies"$ENDCOLOR
echo $ENDCOLOR"using 'check'"
sleep 1
sudo apt-get check

echo $BLUE"removing leftover packagedata"$ENDCOLOR
echo $BLUE"using 'clean'"$ENDCOLOR
sleep 1
sudo apt-get clean

echo $BLUE"removing leftover dependencies"$ENDCOLOR
echo $ENDCOLOR"using 'autoremove'"$ENDCOLOR
sleep 1
sudo apt-get autoremove

echo $BLUE"removing leftover sources"$ENDCOLOR
echo $ENDCOLOR"using 'autoclean'"$ENDCOLOR
sleep 1
sudo apt-get autoclean

echo $BLUE'removing old configfiles'$ENDCOLOR
sleep 1
sudo dpkg -l | grep ^rc | awk '{print $2}' | xargs sudo dpkg --purge

echo $BLUE"emptying every trashes..."$ENDCOLOR
sleep 1
rm -rf /home/*/.local/share/Trash/*/** &> /dev/null
rm -rf /root/.local/share/Trash/*/** &> /dev/null

echo $BLUE"removing 'Flash_Player SharedObjects'"$ENDCOLOR
sleep 1
rm -rf ~/.macromedia/Flash_Player/* 

sleep 2
echo $BLUE"removing old (+7d) thumbnails"$ENDCOLOR
sleep 1
find ~/.thumbnails -type f -atime +7 -exec rm '{}' \;

sleep 2
echo $BLUE"removing old Okular metadata"$ENDCOLOR
cd "$(kde4-config --localprefix)/share/apps/okular/docdata"

for A in *.xml; do
        B=`sed -ne 's/^<documentInfo .*url="\(.\+\)".*>$/\1/p' "$A"`
        [ -f "$B" ] || rm -f "$A"
done

echo $RED"done!"$ENDCOLOR

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17620

Wohnort: Berlin

Wie rufst Du das Skript auf? Mit sh? Damit überstimmst Du den shebang.

Kalter_Stern

(Themenstarter)
Avatar von Kalter_Stern

Anmeldungsdatum:
12. Juni 2009

Beiträge: 218

Ich rufe es mit mit

alias clean='sudo sh ~/.bin/ubucleaner.sh'

also Ja (?)

Aber was heisst das praktisch? Der Wikiartikel hilft mir nicht so arg viel, ehrlich gesagt…

diesch Team-Icon

Avatar von diesch

Anmeldungsdatum:
18. Februar 2009

Beiträge: 5072

Wohnort: Brandenburg an der Havel

Mach das Skript ausführbar mit

1
chmod a+x ~/.bin/ubucleaner.sh

und definiere den Alias dann mit

1
alias clean='sudo ~/.bin/ubucleaner.sh'

Kalter_Stern

(Themenstarter)
Avatar von Kalter_Stern

Anmeldungsdatum:
12. Juni 2009

Beiträge: 218

Cool, danke, so geht es.

Was ist denn jetzt der Unterschied? Ich lasse ja nur das sh im alias weg?

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2510

Expliziter Aufruf des Programms namens „sh“ mit dem Skriptnamen als erstem Argument. Damit sagst du, dass „sh“ das Skript ausführen soll:

sh skriptname.sh

sh“ bedeutet in Ubuntu aber, dass die dash gemeint ist. Du hast ein bash-Skript mit Funktionen, die die dash nicht kennt. Also geht das so nicht.

Machst du das Ding ausführbar und rufst es dann ohne explizite Angabe eines Interpreters auf, so wird die Shebang-Zeile vom Kernel ausgewertet:

chmod u+x skriptname.sh
./skriptname.sh

In deiner Shebang steht die Bash! Und deswegen geht es diesmal.

Kurzum: Bash und sh sind allgemein nicht dasselbe und bei Ubuntu spürst du den Unterschied eben ganz deutlich.

Hilft dir diese Erklärung weiter?

Kalter_Stern

(Themenstarter)
Avatar von Kalter_Stern

Anmeldungsdatum:
12. Juni 2009

Beiträge: 218

Ja, sehr! Vielen Dank dafür!

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17620

Wohnort: Berlin

Kalter Stern schrieb:

Ich rufe es mit mit

alias clean='sudo sh ~/.bin/ubucleaner.sh'
1
alias clean='sudo bash ~/.bin/ubucleaner.sh'

würde auch funktionieren.

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

user unknown schrieb:

1
alias clean='sudo bash ~/.bin/ubucleaner.sh'

würde auch funktionieren.

Aber das wollen wir natürlich gar nicht erst einführen !
(sonst gewöhnt sich jeder Neuling an, grundsätzlich den Shebang zu überrennen, und weiß dabei gar nicht was er tut ...)


Also: bitte noch einmal, zum mitschreiben:

  1. Man mache das Skript "ausführbar"

  2. Man starte das Skript im Terminal mit ./skript

und nicht anders ! - Es sei denn, man weiß was man tut.

LG,

track

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17620

Wohnort: Berlin

track schrieb:

user unknown schrieb:

1
alias clean='sudo bash ~/.bin/ubucleaner.sh'

würde auch funktionieren.

Aber das wollen wir natürlich gar nicht erst einführen !
(sonst gewöhnt sich jeder Neuling an, grundsätzlich den Shebang zu überrennen, und weiß dabei gar nicht was er tut ...)

Der User tut, was er tun will. Meist will er tun, was leichter ist. Führt man ein Programm oft aus ist es leichter, es ein für allemal ausführbar zu machen.

Wenn man es von Dritter Hand hat macht man es auch schneller ausführbar, als erst mit

head -n1 neuesSkript.sh 

nachzusehen, welcher Interpreter der richtige ist.

Schreibt man ein adhoc-Skript für find, das man nur einmal ausführt und dann wegwirft, kann der Bashaufruf einfacher sein, oder die Plustaste ist defekt, dann kann man es mit einem direkten Aufruf der Bash machen - natürlich.

Wer wie ich nie für die Dash schreibt, oder nur in Ausnahmen, und daher weiß, dass im eigenen bin-Ordner unter ~ nur Bashscripte sind - wieso soll der nicht seine Skripte mit bash aufrufen? Im angegebenen Fall wissen wir, dass es ein Bashscript ist.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17620

Wohnort: Berlin

Pardon, Übertragungsfehler - dann war's ein Doppelpost.

Antworten |