Bash/Expansion von Dateinamen: Unterschied zwischen den Versionen
Zeile 255: | Zeile 255: | ||
1 11 111 2 22 222 3 33 333 a aa aaa b bb bbb c cc ccc | 1 11 111 2 22 222 3 33 333 a aa aaa b bb bbb c cc ccc | ||
[[Kategorie:Bash/Expansionen]] | [[Kategorie:Bash/Expansionen]] |
Version vom 9. März 2024, 09:38 Uhr
After word splitting, unless the -f option has been set , Bash scans each word for the characters "*", "?", and "[".
If one of these characters appears, then the word is regarded as a PATTERN, and replaced with an alphabetically sorted list of file names matching the pattern.
If no matching file names are found, and the shell option nullglob is disabled, the word is left unchanged.
If the nullglob option is set, and no matches are found, the word is removed.
If the shell option nocaseglob is enabled, the match is performed without regard to the case of alphabetic characters.
When a pattern is used for file name generation, the character "." at the start of a file name or immediately following a slash must be matched explicitly, unless the shell option dotglob is set.
When matching a file name, the slash character must always be matched explicitly. In other cases, the "." character is not treated specially.
The GLOBIGNORE shell variable may be used to restrict the set of file names matching a pattern.
If GLOBIGNORE is set, each matching file name that also matches one of the patterns in GLOBIGNORE is removed from the list of matches.
The file names . and .. are always ignored, even when GLOBIGNORE is set.
However, setting GLOBIGNORE has the effect of enabling the dotglob shell option, so all other file names beginning with a "." will match.
To get the old behavior of ignoring file names beginning with a ".", make ".*" one of the patterns in GLOBIGNORE. The dotglob option is disabled when GLOBIGNORE is unset.
Metazeichen und Globbing
Damit man beim Angeben von z. B. Dateinamen nicht alle Namen eintippen muss, sondern die Dateien auch alle oder nach bestimmten Kriterien auswählen kann, gibt es Metazeichen (Jokerzeichen, Wildcards).
Metazeichen sind Zeichen mit erweiterter Bedeutung
Expansion von Dateinamen
Im Gegensatz zu anderen Systemen (z. B. Windows) werden Metazeichen von der Shell durch alle passenden Dateinamen ersetzt, bevor sie die Befehlszeile ausführt. Dies führt zu einem für Windows-Anwender ungewohntem Verhalten.
Metazeichen werden von der Shell ersetzt
Vorteile* liegt darin, dass, dass nahezu jedes UNIX-Kommando als Dateiangabe eine beliebige Menge von Dateien als Parameter haben kann.
- So sind in Programmen keine Systemaufrufe nötig, die auf die Verzeichnisinformation zugreifen; es wird lediglich eine Schleife benötigt, welche die einzelnen Dateien nacheinander bearbeitet.
Praktisches Globbing
Ganz schlecht
chmod a+r witzig1.jpg chmod a+r witzig2.jpg chmod a+r witzig3.jpg
Besser
chmod a+r witzig1.jpg witzig2.jpg witzig3.jpg
Super
chmod a+r *.jpg
Es gibt folgende Metazeichen
* | Der Stern steht für eine beliebige Zeichenfolge - oder für überhaupt kein Zeichen.
"ab*" steht für alle Dateinamen, die mit "ab" anfangen, auch für "ab" selbst ("ab", "abc", "abcd", "abxyz", usw.). |
? | Das Fragezeichen steht für genau ein beliebiges Zeichen. Zum Beispiel
"?bc" steht für alle Dateinamen mit 3 Zeichen, die auf "bc" enden ("abc", "bbc", "1bc", "vbc", "xbc", usw.), nicht jedoch für "bc". |
[...] | Im einfachsten Fall steht es für genau ein Zeichen aus der Menge (bspw. "[aeiou]" für einen Vokal).
Diese Angabe kann negiert werden ("alle außer diese Zeichen"), indem das erste Zeichen nach [ ein ! oder ^ ist ("[!abc]" bzw. "[^abc]"). Anstatt einzelne Zeichen aufzuzählen, lassen sich Bereiche angeben ("[a-z]" meint alle Kleinbuchstaben). |
Wichtig!
Der * ist ein gefährliches Zeichen, Tippfehler könne zum Fiasko führen, wenn aus Versehen ein Leerzeichen zuviel getippt wird.
rm a* löscht beispielsweise alle Dateien, die mit "a" anfangen. rm a * löscht dagegen erst die Datei "a" und dann alle Dateien im Verzeichnis.
Zeichenbereiche
Außer grep und Regulären Ausdrücken, gibt es eine gute Auswahl an pattern matching, dass die Shell direkt durchführen kann, ohne dass dafür externe Programme eingesetzt werden müssen.
Bekannt sind sicherlich das Sternchen (asterisk) „*“ und das Fragezeichen (question mark) „?“, die jede Zeichenkette oder jeden Buchstaben filtern. Um diese Sonderzeichen als Literale zu filtern müssen sie maskiert werden:
touch "*" ls "*" *
But you can also use the square braces to match any enclosed character or range of characters, if pairs of characters are separated by a hyphen. An example:
ls -ld [a-cx-z]* drwxr-xr-x 2 dirkwagner dirkwagner 4096 Jul 20 2002 app-defaults/ drwxrwxr-x 4 dirkwagner dirkwagner 4096 May 25 2002 arabic/ drwxrwxr-x 2 dirkwagner dirkwagner 4096 Mar 4 18:30 bin/ drwxr-xr-x 7 dirkwagner dirkwagner 4096 Sep 2 2001 crossover/ drwxrwxr-x 3 dirkwagner dirkwagner 4096 Mar 22 2002 xml/
This lists all files in dirkwagner's home directory, starting with "a", "b", "c", "x", "y" or "z".
If the first character within the braces is "!" or "^", any character not enclosed will be matched.
To match the dash ("-"), include it as the first or last character in the set.
The sorting depends on the current locale and of the value of the LC_COLLATE variable, if it is set.
Mind that other locales might interpret "[a-cx-z]" as "[aBbCcXxYyZz]" if sorting is done in dictionary order.
If you want to be sure to have the traditional interpretation of ranges, force this behavior by setting LC_COLLATE or LC_ALL to "C".
Nullglob
Ohne Match wird das Argument unverändert übernommen. Dieses Verhalten lässt sich mit der Shelloption nullglob beeinflussen.
Match - gefundene Dateien werden übernommen
echo a1*.jpg a1.jpg a10.jpg a11.jpg
Kein Match - Argument bleibt unverändert
echo b1*.jpg b1*.jpg
Dotfiles
Der Punkt am Anfang von Dateinamen stellt eine Ausnahme dar, er muss explizit angegeben werden (wegen der Verzeichnisreferenzen "." bzw. ".." und der Tatsache, dass Dateien, die mit einem Punkt beginnen, normalerweise nicht angezeigt werden). * Dateien, die mit "." beginnen sind versteckt
- Shell Globbing ignoriert die "Dotfiles"
- Punkt muss explizit genannt werden
echo .* . .. .bash_history .bash_profile .bashrc
Globbing und Brace Expansion
Brace Expansion hat starke Ähnlichkeit mit Globbing doch die angegebenen Dateinamen müssen nicht existieren.
ls a1.jpg a10.jpg a11.jpg a2.jpg a3.jpg a4.jpg
"{name1,name2}" - Alternativen aufzählen
echo a{2,10}.jpg a2.jpg a10.jpg
Zeichenklassen
Zeichenklassen können mit folgender Syntax in eckigen Klammen angegeben [:CLASS:]. Dabei wird CLASS nach POSIX-Standard angegeben und kann folgende Werte annehmen:
"alnum", "alpha", "ascii", "blank", "cntrl", "digit", "graph", "lower", "print", "punct", "space", "upper", "word" or "xdigit"
ls -ld digit:* drwxrwxr-x 2 dirkwagner dirkwagner 4096 Apr 20 13:45 2/
ls -ld upper:* drwxrwxr-- 3 dirkwagner dirkwagner 4096 Sep 30 2001 Nautilus/ drwxrwxr-x 4 dirkwagner dirkwagner 4096 Jul 11 2002 OpenOffice.org1.0/ -rw-rw-r-- 1 dirkwagner dirkwagner 997376 Apr 18 15:39 Schedule.sdc
Wenn die Shell-Option extglob aktiviert ist, werden erweiterte pattern matching Operatoren erkannt.
Extglob (erweitertes Globbing)
Die ksh88 führte zusätzlich die erweiterte Mustererkennung ein. Diese sind vergleichbar mit der Leistung Regulärer Ausdrücke, die Notation ist ähnlich, aber nicht gleich. Wenn die Shelloption extglob eingeschaltet ist, unterstützt auch die Bash diese Optionen.
Wenn möglich, sollte die erweiterte Mustererkennung regulären Ausdrücken vorgezogen werden, da diese effizienter und damit deutlich schneller ausgewertet werden können. Die Muster sind eine Liste von Zeichenketten, die durch | getrennt sind.
Das Zeichen vor der öffnenden Klammer reguliert die Auswertung des Musters:
?(Muster-Liste) | Kein oder ein Auftreten eines Musters |
*(Muster-Liste) | Kein oder mehrere Auftreten eines Musters |
+(Muster-Liste) | Ein oder mehrere Auftreten eines Musters |
@(Muster-Liste) | Genau ein Auftreten eines Musters |
!(Muster-Liste) | Alle außer den angegebenen Mustern |
Die erweiterte Mustererkennung kann mit Standard-Shell-Wildcards kombiniert und verschachtelt werden.
Übungen 1
Vorbereitung
mkdir ~/gob && cd ~/gob touch a aa aaa b bb bbb c cc ccc d dd ddd# Beliebig viele beliebige Zeichen (*)
ls a* a aa aaa# Ein beliebiges Zeichen (?)
ls a? aa# Ein Zeichen aus einer Menge [...]
ls [abc] a b c# Ein Zeichen aus einem Bereich [ - ]
ls [a-d] a b c d# Kein Zeichen aus der Menge [! ]
ls [!ab]* c cc ccc d dd ddd# Kein Zeichen aus einem Bereich [! - ]
ls [!a-c]* d dd ddd
Übungen 2
Vorbereitung
mkdir ~/extgob && cd ~/extgob touch 1 11 111 2 22 222 3 33 333 touch a aa aaa b bb bbb c cc ccc# ?(Muster-Liste)- kein oder ein Auftreten eines Musters
ls ?(a|b) a b# *(Muster-Liste) - kein oder mehrere Auftreten eines Musters
ls *(a|b) a aa aaa b bb bbb# +(Muster-Liste) - ein oder mehrere Auftreten eines Musters
ls +(a|b) a aa aaa b bb bbb# @(Muster-Liste) - genau ein Auftreten eines Musters
ls @(a|b) a b# !(Muster-Liste)- alle außer den angegebenen Mustern
ls !(a|b) 1 11 111 2 22 222 3 33 333 aa aaa bb bbb c cc ccc# .!(|.) - Dotfiles ohne "." und ".."
ls -d .!(|.) .bash_history .bash_profile .bashrc
Zeichenklasse
- [[:Zeichenklasse:]]
ls [[:alpha:]] a b c# Kombinationen
ls +([[:digit:]]) 1 11 111 2 22 222 3 33 333
ls ?([[:digit:]]) 1 2 3
ls +([[:digit:]]|!([[:upper:]])) 1 11 111 2 22 222 3 33 333 a aa aaa b bb bbb c cc ccc