1: Einführung
1.1: Wer bin ich?
- Jens Giessmann
- Angestellter bei LF.net einem Stuttgarter ISP
- Seit 2000 tätig in den Bereichen Webserver-Administration, Support und Entwicklung
- Seit 2001 PHP-Entwickler
- Zend Certified Engineer
1.2: Wer seid ihr?
Fragen zum background:
- Wer administriert Unix Server?
- Wer arbeitet in der Shell?
- Wer hat Unix als Arbeitsplatz?
1.3: Agenda
- Einführung
- Hilfe
- Grundlagen
- Shell Basics
- Umleitungen
- Shell Scripts
- Multitasking
- Suchen und finden
- Tips und Tricks
1.4: Warum...
Warum Unix?
- Webserver laufen mit Unix.
- Unix ist das bessere OS-Konzept.
Ok, aber warum in der Shell?
- Die Shell geht immer, egal ob lokal oder remote.
- Die Shell ist von Programmierern für Programmierer.
- Shell Kommandos sind leicht automatisierbar.
- Die meisten GUI Applikationen sind "nur" grafische Oberflächen für Kommandos, die man auch direkt in der Shell ausführen kann.
Hat man sich einmal an die Macht der Textkonsole gewöhnt,
will man diese nicht mehr missen.
2: Hilfe
2.1: Lesen bildet, Doku hilft
RTFM
- Unix hat von Anfang an (als erstes OS ?) eine komplette Online-Dokumentation mit dabei.
- Es gibt sehr viele und auch sehr gute Bücher zu allen möglichen Unix-Themen.
- Im Web findet man sehr viel Dokumentation zu den diversen Themen und Problemen.
- Die Arbeitsweise und die Kommandos sind im Prinzip bei den verschiedenen Unix-Derivaten gleich. Hat man das Prinzip einmal verstanden und weiss was man braucht, kommt man auf allen Unix Systemen (mehr oder weniger) schnell zurecht.
Doku schreiben
- Alle Arbeiten in der Shell sind gut dokumentierbar und reproduzierbar.
- Mitschreiben hilft sich an bereits gelöste Probleme zu erinnern.
2.2: Was? Wo? Wie?
Was?
whatis <string>
apropos <string>
Wo?
which <command>
whereis <command>
Wie?
man <command>
info <command>
<command> -h | --help
3: Grundlagen
3.1: Wohlfühlumgebung
Unix ist ein MultiUser-System.
Jeder User hat sein HOME in dem er sich seine "Wohlfühlumgebung" einrichten und stetig weiter entwickeln kann.
Die persöhnlichen Einstellungen, Anpassungen, usw. werden in den sogenannten DOT-Files abgelegt.
-rw-r----- 1 jg users 4573 Jan 8 18:38 .bashrc -rw-r--r-- 1 jg users 22351 Dec 30 13:59 .emacs -rw-r--r-- 1 jg users 2167 Jan 6 15:21 .profile -rw-r----- 1 jg users 698 Apr 30 2007 .screenrc drwx------ 3 jg users 102 Dec 22 2008 .ssh/ drwxr-xr-x 11 jg users 374 Jan 21 16:38 .xemacs/ ...
Tip: Die wichtigsten DOT-Files zur einfachen Verteilung und Aktualisierung auf verschiedenen Maschinen mit CVS/SVN verwalten.
Eigene kleine Tools und Hilfsprogramme sind in ~/bin/ gut aufgehoben.
3.2: Editoren
Ohne einen vernünftigen Text-Editor, mit dem man sich gut auskennt, geht unter Unix gar nichts.
Beim Thema Editoren teilt sich die Unix-Welt in 2 Lager:
(X)Emacs | vi(m)
Man muss sich entscheiden. Das Leben ist zu kurz um beide zu lernen ;-)
- vi(m) ist per Default auf (fast) jedem System installiert
- Beide sind für praktische jede Plattform verfügbar
- Beide können VIEL mehr als man am Anfang denkt
- Beide können sehr gut an die individuelle Arbeitweise angepasst werden
Meine Empfehlung ist natürlich (X)Emacs ;-)
Eine Einführung in diese beiden Editoren würde locker 1-n eigene Vorträge füllen, daher geh ich hier auch gar nicht weiter drauf ein.
Kleine Demo?
4: Shell Basics
4.1: Was ist eine Shell?
Die Shell ist Benutzerschnittstelle und Kommandozeileninterpreter
- Bietet einen Prompt für die Eingaben von Kommandos an
- Liest und interpretiert die Eingaben
- Führt Kommandos in Subprozessen aus und zeigt die Ausgabe an
- Bietet Scriptsprache zur Programmierung und Automatisierung von Aufgaben
Verschiedene Shells für verschiedene Vorlieben und Anforderungen.
Bourne shell, Korn shell, C shell, Bourne-Again shell (bash), ...weitere
Alle Beispiele in diesem Vortrag basieren auf der bash
4.2: Viele kleine Kommandos
- Unix Kommandos führen meist nur eine einzige mehr oder weniger kleine Aufgabe aus, diese aber möglichst perfekt.
- Komplexere Aufgaben werden durch Kombinationen mehrerer dieser kleinen Kommandos gelöst.
- Durch diese Kombinierbarkeit entsteht ein extrem flexibles und mächtiges "Power-Tool".
- Durch die schiere Masse an möglichen Kommandos, die z.T. noch wenig intuitive Namen haben oder mit kryptischen Parametern aufgerufen werden müssen, ist die Einstiegshürde zu diesem "Power-Tool" allerdings recht hoch.
4.3: Wichtige Kommandos (1)
Kommandos zum Bewegen im und Bearbeiten des Dateisystems:
- cd
- In ein anderes Verzeichnis wechseln
- pwd
- Ausgabe des aktuellen Verzeichnisses
- ls
- Dateien und Verzeichnisse im Dateisystem anzeigen
- cp
- Kopieren von Dateien und Verzeichnissen
- mv
- Umbenennen von Dateien und Verzeichnissen
- rm
- Löschen von Dateien und Verzeichnissen
4.4: Wichtige Kommandos (2)
Kommandos zur Anzeige von Dateiinhalten:
- cat
- Ausgabe des Inhalts einer Datei
- more
- Seitenweise Anzeige des Inhalts einer Datei
- less
- Seitenweise Anzeige des Inhalts einer Datei mit mehr Möglichkeiten als more sie bietet (less is more)
- head
- Anzeige der n ersten Zeilen einer Datei
- tail
- Anzeige der n letzten Zeilen einer Datei
4.5: Wichtige Kommandos (3)
Kommandos zur Arbeit mit Dateien:
- find
- Durchsucht das FileSystem nach Mustern
- grep
- Durchsucht Inhalte nach Mustern
- sort
- Sortiert Inhalte anhand bestimmter Felder (zeilenweise)
- cut
- Extrahiert bestimmte Felder aus Inhalten (zeilenweise)
- uniq
- "Zusammenkochen" von Inhalten auf eindeutige Werte (zeilenweise)
- split
- Aufteilen von Dateien in Teile mit n Zeilen
4.6: Wichtige Kommandos (4)
Kommandos für Webfuzzys:
- php
- Ja, geht auch sehr gut in der Shell ;-)
- wget
- Download Tool für http und ftp
- curl
- "Client for URLs", kann HTTP, HTTPS, FTP, FTPS, SCP, SFTP,...
- telnet
- Client für interaktive TCP-Verbindungen
- mysql
- phpMyAdmin ist nur eine Krücke wenn man keine Shell hat ;-)
- whois
- Domain und IP Abfragen (wem gehört was)
- host, dig, nslookup
- DNS Abfragen
4.7: Parameter und Optionen (1)
Unix-Kommandos haben meist diverse Parameter und Optionen.
- Parameter und Optionen beginnen in der Regel mit einem - (Minus). Bsp: cmd -a oder cmd -param
- Parameter und deren Argumente werden in der Regel mit einem Leerzeichen getrennt. cmd -a value oder cmd -param value
- Parameter ohne Argumente können zusammengfasst werden, die Reihenfolge ist egal, d.h. cmd -a -b ist identisch zu cmd -ab oder cmd -ba
Aber...
-
Nicht alle Kommandos halten sich an diese Regeln. Bsp:
dd if=/dev/zero of=./40mb bs=40960 count=1024 - Kommandos sind in verschiedenen Unix-Derivaten z.T. unterschiedlich implemetiert und haben unterschiedliche Parameter und Optionen, RTFM.
ps [-aCcefHhjlmrSTuvwXxZ] [-O fmt | -o fmt] [-G gid[,gid...]] [-M core]
[-N system] [-p pid[,pid...]] [-t tty[,tty...]] [-U user[,user...]]
ps [-aAcdefjlLPyZ] [-g grplist] [-n namelist] [-o format] [-p proclist]
[-s sidlist] [-t term] [-u uidlist] [-U uidlist] [-G gidlist] [-z zonelist]
4.8: Parameter und Optionen (2)
- Parameter und Optionen mit Sonderzeichen wie ()|$;\#*`"', die NICHT von der Shell interpretiert werden sollen, müssen escaped werden.
-
Richtig:
X
gzip *.log
Xgrep -E '^\s*(#|//)' script.php
-
Falsch:
X
grep -E ^\s*(#|//) script.php bash: syntax error near unexpected token `('
4.9: Parameter am Beispiel ls
- ls [-ABCFGHLPRSTW@abcdefghiklmnopqrstuwx1] [file ...]
- ...stattliche Liste für so ein "simples" Kommando, da hilft nur: RTFM
- ls
- Dateien und Verzeichnisse im aktuellen Verzeichnis anzeigen (ohne DOT-Files)
- ls -a
- Alle Dateien (auch DOT-Files) und Verzeichnisse im aktuellen Verzeichnis anzeigen
- ls -l
- Anzeige in der Langform mit Rechten, timestamps, Größe
- ls -1
- Kurzform, je Datei/Verzeichnis eine Zeile, praktisch in Scripten
- ls -altr
- Alle Dateien und Verzeichnisse, Langform, sortiert nach timestamp, neueste Dateien unten
Mit der Zeit bekommt man Übung im Querlesen von man-pages und findet recht schnell was man wie machen muss.
5: Umleitungen
5.1: Input und Output (1)
Unix bietet 3 Standard I/O streams für Eingaben und Ausgaben die weiter- oder umgeleitet werden können:
- standard input (STDIN)
- standard output (STDOUT)
- standard error (STDERR)
| Was | Wie (sh) |
|---|---|
| STDOUT in Datei schreiben | prog > file |
| STDERR in Datei schreiben | prog 2 > file |
| STDOUT und STDERR in Datei schreiben | prog > file 2>&1 |
| STDOUT am Ende einer Datei anfügen | prog >> file |
| STDERR am Ende einer Datei anfügen | prog 2 >> file |
| STDIN aus Datei lesen | prog < file |
| STDIN aus Keyboard-Eingabe (bis ^c) lesen | prog << c |
| STDOUT an STDIN von prog2 weiterleiten (Pipe) | prog | prog2 |
| STDOUT und STDERR an STDIN von prog2 weiterleiten (Pipe) | prog 2>&1 | prog2 |
Die Syntax für I/O Umleitungen ist in den verschiedenen Shells z.T. leicht unterschiedlich! RTFM
5.2: Input und Output (2)
- Input kann aus einer Datei, durch Keyboard-Eingabe oder über STDIN gelesen werden
- Output kann in eine Datei geschrieben, im Terminal ausgegeben oder direkt an ein weiteres Kommando übergeben werden.
Weiterleitungen von STDIN, STDOUT und STDERR können im selben Kommando kombiniert werden.
prog < input > output 2> errors
jg@home:~$ cat << . > out > eine Eingabe uebers Keyboard > kann auch mehrzeilig sein > . jg@home:~$ cat out eine Eingabe uebers Keyboard kann auch mehrzeilig sein jg@home:~$
5.3: Pipes
Über die Pipe (|) können Ausgaben eines Kommandos direkt als Eingabe zum nächsten Kommando weitergeleitet werden.
Damit können mehrere kleine Kommandos zu "Meta-Tools" kombiniert werden.
cat file | mail -s "tolles file" jg
Die Pipe "verbindet" STDOUT des linken Kommandos (cat) mit STDIN des rechten Kommandos (mail).
Mit Pipes lassen sich beliebig komplexe Kommando-Ketten erstellen.
zcat 20050426.gz | cut -d" " -f1 | sort | uniq | wc -l
TMPDATE=$(/bin/date "+%Y-%m"); cut -d " " -f 3 ~/Mail/.logs/$TMPDATE | sort | uniq -c | sort -r | head -n 5 | \ tee ~/Mail/.logs/top5-$TMPDATE | mail -s "top5-$TMPDATE" jg
6: Shell Scripts
6.1: Basics
Ein Shell Script ist eine Datei, in der Shell-Kommandos zu einem Programm zusammen gefasst sind.
#!/bin/bash echo "Hello World";
Bei der Ausführung eines Shell-Scripts wird eine Shell gestartet und die enthaltenen Kommandos ausgeführt.
Shell-Scripts bieten die üblichen Möglichkeiten von Scriptsprachen: Variablen, Schleifen, Konditionen, Funktionen, etc.
Viele Shell Scripts entstehen durch Zusammenfassung von immer wiederkehrenden Kommando-Folgen in einer Datei, einem Shell Script.
Durch den direkten Zugriff in Shell-Scripts auf alle Unix-Konsolen-Tools können oft mit wenigen Zeilen mächtige Tools gebaut werden, die in anderen Sprachen oft viel aufwändiger wären.
6.2: if, elif, else, case
if, elif, else
if [ -f /tmp/einedatei ] then mv /tmp/einedatei ~/anderedatei elif [ -d /tmp/einverzeichnis ] then cp -r /tmp/einverzeichnis ~/anderesverzeichnis else echo "Keine Datei gefunden" fi
case
case $filename in
*.gz)
gunzip $filename
;;
*.bz2)
bunzip2 $filename
;;
*)
echo "Archive format ist unbekannt."
exit
;;
esac
6.3: Loops, Funktionen
for loop
for FILE in *.gz do gunzip $FILE done
while loop
zaehler=1
while [ $zaehler -le 10 ]
do
date;
sleep 1;
zaehler=`expr $zaehler + 1`
done
Funtionen
function my_message () {
echo $1;
}
my_message "hallo welt"
-> hallo welt
7: Multitasking
7.1: Subshells mit ( )
Kommandos in ( ) werden in Subshells ausgeführt.
Mit Subshells können Ausgaben von mehreren Kommandos (STDOUT und STDERR) zusammengefasst oder die Umgebung temporär verändert werden.
(cmd1; cmd2; ...) > all-cmds.out
Subshells sind völlig getrennt von der aufrufenden Shell
$ pwd /users/jg (cd /irgendwo/ganz/anders; cat file1 > file1.out ) $ pwd /users/jg
Praktisch auch, um mit Loops über von Kommandos erstellte dynamische Listen zu iterieren.
for LOG in $(ls -1 /var/log/apache/log.2008*) do runstats $LOG done
7.2: Job Control - was läuft?
ps
$ ps ux | more USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND jg 55475 0.0 0.4 8432 4000 ?? R 5:51PM 0:00.09 sshd: jg@ttyp0 (sshd) jg 1126 0.0 0.2 4360 2296 v0 I+ 23Jun09 0:00.02 -bash (bash) jg 55670 0.0 0.2 3580 1812 p0 S+ 6:39PM 0:00.05 screen -d -r jg 1175 0.0 0.2 4364 2336 p1 Is 23Jun09 0:00.05 /bin/bash jg 54902 0.0 0.8 11764 8144 p1 I+ 2:31PM 0:03.37 mutt ...
top
last pid: 56388; load averages: 0.00, 0.00, 0.00 up 11+03:25:32 22:24:30 77 processes: 1 running, 76 sleeping CPU: 0.0% user, 0.0% nice, 1.9% system, 0.0% interrupt, 98.1% idle Mem: 78M Active, 626M Inact, 148M Wired, 952K Cache, 111M Buf, 139M Free Swap: 1024M Total, 1024M Free PID USERNAME THR PRI NICE SIZE RES STATE TIME WCPU COMMAND 965 mysql 11 45 0 198M 40196K ucond 0:38 0.00% mysqld 51794 www 1 20 0 23924K 17292K lockf 0:00 0.00% apache 835 root 1 8 0 23888K 17264K nanslp 0:27 0.00% apache 55950 www 1 20 0 23888K 17264K lockf 0:00 0.00% apache 1172 jg 1 44 0 16892K 16076K select 0:17 0.00% screen 55472 root 1 4 0 8432K 3976K sbwait 0:00 0.00% sshd 985 mailnull 1 44 0 8180K 3140K select 0:01 0.00% exim-4.69-4 1015 root 1 8 0 7248K 5184K nanslp 0:30 0.00% perl ...
7.3: Job Control (1)
Ein Prozess anhand der PID killen
kill PID
Prozess anhand des Prozessnamens killen
killall cmd
Kommando abbrechen (killen)
CTRL-c
Kommando starten und im Hintergrund laufen lassen
cmd &
Kommando stoppen und in den Hintergrund stellen
CTRL-z
7.4: Job Control (2)
Anzeige von Hintergund-Jobs mit deren Job-Nummer
jobs
Einen Hintergrund-Job wieder in den Vordergrund holen
fg %num
Gestoppten Job im Hintergrund weiterlaufen lassen
bg %num
Hintergrund-Job killen
kill %num
7.5: Screen
Screen ist ein "Windowmanager" für Shells.
Screen erstellt und verwaltet virtuelle Terminals für Shells.
Möglichkeiten und Vorteile von screen:
- Mehrere Shells "hintereinander" laufen lassen
- Persistenter "Arbeitsplatz"
- "Arbeitsplatz" kann dezentral (wieder) verwendet werden
- Shells im screen und Prozesse darin, laufen solange sie nicht gestoppt werden, unabhängig vom physikalischen Terminal
Kleine Demo?
8: Suchen und finden
8.1: find
find ist eines der mächtigsten und nützlichsten Tools in Unix-Shells.
- Anhand von Mustern nach Dateien und Verzeichnisse suchen.
-
Muster können für praktisch alle Informationen, die das
Filesystem bietet angegeben werden.
Name, Rechte, Typ, Größe, Zugriffszeiten, ... - Mehrere Muster werden mit logischem UND/ODER verknüpft, können negiert und gruppiert werden.
- Mit verschiedenen Parametern können Aktionen definiert werden, die für Treffer der Suche ausgeführt werden (-print, -ls, -exec).
- Logische UND/ODER Verknüpfungen der Parameter werden von links nach rechts geprüft. Komplexe find Kommandos sollten so geschrieben werden, dass die Reihenfolge möglichst "performant" ist.
8.2: find - Beispiele (1)
PHP Session Files in /tmp, die leer UND älter als 24h sind.
find /tmp/ -name "sess_*" -size 0 -ctime +1
Dateien, die neuer als die Datei .TIMEREF sind, mit ls -al anzeigen lassen
find . -type f -newer .TIMEREF -exec ls -al {} \;Tip: Mit dem Kommando touch kann man Dateien wie hier .TIMEREF explizite timestamps vergeben.
Dateien in /tmp, deren Name mit fw_cache* anfängt UND die innerhalb der letzten 3 Tage nicht geändert wurden löschen
find /tmp/ -name "fw_cache*" -mtime +3 -exec rm -f {} \;Die selbe Liste zum Löschen an xargs übergeben.
find /tmp/ -name "fw_cache*" -mtime +3 | xargs rm
xargs führt für eine beliebige Liste von Werten das angegebene Kommando aus.
8.3: find - Beispiele (2)
Alle Files, die bisher der uid 69 gehören, dem User www-data schenken.
find . -uid 69 -print0 | xargs -0 chown www-data
Mit -print0 werden Pfadangaben in der Ausgabe 0-byte
terminiert.
Nützlich, um z.B. Probleme mit Leer- oder Sonderzeichen in
Dateinamen zu umgehen, wenn diese als Parameter weiter
verwendet werden sollen.
Mehrere verschiedene find-Befehle in einem Kommando kombinieren.
find . \( -type d -a -exec chmod 774 {} \; \) -o \
\( -name "*.BAK" -a -exec chmod 600 {} \; \) -o \
\( -name "*.sh" -a -exec chmod 755 {} \; \) -o \
\( -name "*.txt" -a -exec chmod 644 {} \; \)So können mehrere Aufgaben mit nur einer Suche über das FileSystem erledigt werden.
Escaping (\) der Klammern und der Semikolons ist nötig, da sonst die Shell diese interpretieren und nicht an find durchreichen würde.
8.4: grep (1)
Mit grep ist es möglich Dateiinhalte nach RegEx-Pattern zu durchsuchen.
grep PATTERN file
grep kann in einem Aufruf mehrere Dateien durchsuchen
grep '<h1 class="title">' slide-*.html slide-1.html: <h1 class="title">Einführung</h1> ...
grep kann Inhalte auch über pipes auf SDTIN lesen
ps -aux | grep inetd
Die Suche kann natürlich auch umgekehrt werden (-v)
grep -v PATTERN file
8.5: grep (2)
Für extended RegEx grep -E oder egrep verwenden
egrep -v '^\s*(#|//)' script.php
Nicht die Trefferzeile(n), sondern nur den Dateinamen ausgeben und die Suche nach erstem Treffer pro Datei beenden
grep -l XSLT ./* ./xphp-slides.php ./xphp-slides.xsl
Brute-Force-Suche mit grep geht auch, kann aber ein wenig länger dauern ;-)
grep -rs Suchwort /
8.6: find, grep
Kombiniert man find und grep, können sehr feine Volltext-Suchen über ganze Verzeichnis-Bäume erstellt werden.
Suche mir alle .php Files, in denen ein XsltProcessor Objekt initialisiert wird (caseinsensitiv) und gib für Treffer den Dateinamen, die Zeilennummer und die Zeile selber aus. Fehler, z.B. weil für Dateien keine Leserechte bestehen, interessieren mich hier nicht.find . -type f -name "*.php" -print0 2>/dev/null \ | xargs -0 grep -n -H -i 'new xsltprocessor' ./xphp-slides.php:114:$xslt = new XsltProcessor;
8.7: find, grep, sed
Mit der Weitergabe der Dateinamen von Treffern einer solchen Suche an einen Stream-Editor wie sed kann das Bearbeiten von Dateien automatisiert werden, z.B. für Refactoring.
Suche alle PHP Files, in denen noch die alten $HTTP_GET_VARS verwendet werden und ändere dies in $_GET um.Als ein Komando; geänderte Inhalte auf SDTOUT ausgeben
find . -type f -name "*.php" | xargs grep -l \$HTTP_GET_VARS \
| xargs sed s/\$HTTP_GET_VARS/\$_GET/g
Wenn man die Files gleich autom. ändern möchte, und dabei gleich noch Backup-Files der Orginale anlegen will, kann man das mit einem kleinen Shell-Script machen.
for FILE in $(find . -type f -name "*.php" | xargs grep -l \$HTTP_GET_VARS) do sed s/\$HTTP_GET_VARS/\$_GET/g $FILE > $FILE.tmp mv $FILE $FILE.orig mv $FILE.tmp $FILE done
Mit solch "kleinen" Shell-Scripten kann man sich beliebige Auto-Editoren bauen.
9: Tips und Tricks
9.1: Weniger tippen
Command-Line
- Autovervollständigen von Pfaden/Kommandos mit TAB
- Wildcards nutzen (ls -al *.jpg)
- History nutzen
- History Suche nutzen (CTRL-R)
- Readline Movement-Keys verwenden (CTRL-a, CTRL-e,...)
- Readline Edit-Keys verwenden (CTRL-k, M-d,...)
Shortcuts
- Aliase für oft verwendete Kommandos
alias l='ls -laF | more' - Sym-Links in oft verwendete Verzeichnisse
9.2: Nützliches
Logfiles "mitlesen"
tail -f /var/log/php/error
Bereits komprimierte Logfiles lesen/durchsuchen
zcat logfile.gz
zgrep PATTERN logfile.gz
Random Passworte erzeugen
apg
Alle 5 Sekunden ein Kommando ausführen, z.B. die top 10 Prozesse des Users jg die am meisten Memory verbrauchen
watch -n 2 "ps awux -U jg -m | head -n 10"
Alle PHP Files die in den letzten 2 Tagen editiert wurden
find . -type f -name "*.php" -mtime -2
PHP Syntax Check über Verzeichnisse
find . -name \*.php -exec php -l {} \; | grep -v 'No syntax errors'
9.3: Nicht nur Text
Neben Arbeiten mit Text lassen sich in der Shell auch noch ganz andere Aufgaben erledigen, wenn die entsprechenden Programme installiert sind.
Bildbearbeitung
mkdir thumbnails; for IMG in *.[Jj]?([Ee])[Pp][Gg] do convert -resize 150x150 $IMG thumbnails/$IMG done
Audiodateien bearbeiten
EXPORTDIR='/tmp/wav-files' for MP3 in * do WAV=$(echo $WAV | sed 's/\.mp3$/.wav/') /usr/local/bin/lame --decode $MP3 $EXPORTDIR/$WAV done
10: Links
Lesestoff:
Editoren:
11: ...das war's
Vielen Dank für die Aufmerksamkeit.
Fragen?