Όταν εργαζόμαστε από τη γραμμή εντολών ενός συστήματος, προφανώς είναι σχεδόν αναγκαία μια μέθοδος η οποία να μας επιτρέπει να γράψουμε πολλά «στοιχεία» πληκτρολογώντας λίγα. Το κέλυφος bash μας δίνει δυο εργαλεία για τη διευκόλυνση μας. Το πρώτο είναι η αυτόματη συμπλήρωση ονομάτων αρχείων (). Το δεύτερο εργαλείο () είναι οι χαρακτήρες μπαλαντέρ (wildcards).
Καθώς στο κέλυφος [] πληκτρολογούμε μια αναφορά σε ένα όνομα αρχείου,
μπορούμε να πατήσουμε το πλήκτρο “Tab” και το κέλυφος να συμπληρώσει αυτόματα το όνομα αρχείου.
Έστω ότι μέσα σε έναν κατάλογο υπάρχουν τα αρχεία test.txt
και file.txt
και θέλουμε να πληκτρολογήσουμε την εντολή ls -l file.txt
, μπορούμε να πληκτρολογήσουμε μόνο το
ls -l f
και να πατήσουμε το πλήκτρο “Tab”. Το κέλυφος αυτόματα θα συμπληρώσει το όνομα αρχείου.
Στην περίπτωση που στον φάκελο υπάρχουν πολλά αρχεία που ξεκινούν με το ίδιο γράμμα, τότε το κέλυφος θα συμπληρώσει μόνο τους χαρακτήρες οι οποίοι είναι κοινοί σε όλα τα ονόματα αρχείων. Παράδειγμα, έστω σε έναν κατάλογο υπάρχουν τα παρακάτω αρχεία:
asidirop@antonis-PC:/tmp/tests$ ls -l
total 0
-rw-rw-r-- 1 asidirop asidirop 0 Mar 14 22:23 file1.txt
-rw-rw-r-- 1 asidirop asidirop 0 Mar 14 22:23 file2
-rw-rw-r-- 1 asidirop asidirop 0 Mar 14 22:23 file.txt
-rw-rw-r-- 1 asidirop asidirop 0 Mar 14 22:23 test.txt
asidirop@antonis-PC:/tmp/tests$ ls -l f█
Εάν κατά την πληκτρολόγηση του ονόματος αρχείου πληκτρολογήσουμε μόνο το "f"
και μετά πατήσουμε το
πλήκτρο “Tab”, τότε το κέλυφος θα αναγνωρίσει ότι τα αρχεία file1.txt
, file2
και file.txt
ξεκινούν όλα με "f"
και ταιριάζουν σε αυτό που ξεκινήσαμε να πληκτρολογούμε.
Θα συμπληρώσει μόνο τους κοινούς χαρακτήρες, δηλαδή θα συμπληρώσει το "f"
με το ile
που είναι οι κοινοί χαρακτήρες, και θα σταματήσει η αυτόματη συμπλήρωση.
Σε αυτό το σημείο, εάν ξαναπατήσουμε το πλήκτρο “Tab”, θα μας εμφανίσει όλες τις δυνατές επιλογές, δηλαδή:
asidirop@antonis-PC:/tmp/tests$ ls -l file
file1.txt file2 file.txt
asidirop@antonis-PC:/tmp/tests$ ls -l file█
Από εκεί και μετά μπορούμε να συνεχίσουμε την πληκτρολόγηση του ονόματος αρχείου και να ξαναπατήσουμε “Tab”.
Παράδειγμα, αν πληκτρολογήσουμε το ένα (“1”) και έπειτα το “Tab”, τότε το κέλυφος θα
αναγνωρίσει ότι ζητείται αναφορά στο αρχείο file1.txt
και θα συμπληρώσει ολόκληρο το όνομα αρχείου.
Προφανώς, η αυτόματη συμπλήρωση ισχύει όχι μόνο για ονόματα αρχείων, αλλά και για ονόματα καταλόγων.
asidirop@antonis-PC:/tmp/tests$ ls -l /tmp/t
tests/ tmp6VdHaF tmp8DwO_C
asidirop@antonis-PC:/tmp/tests$ ls -l /tmp/t█
Η πληκτρολόγηση του “Tab” μετά από το "/t"
εμφάνισε ότι δυνατές επιλογές είναι οι tests/
, tmp6VdHaF
και tmp8DwO_C
. Μάλιστα μας δίνεται και η πληροφορία ότι το tests
είναι
κατάλογος προσθέτοντας στο τέλος του ονόματος καταλόγου και τον χαρακτήρα "/"
.
Χαρακτήρες Μπαλαντέρ
Wildcards
Εάν θέλουμε, μπορούμε να διαγράψουμε πολλά αρχεία με μια εντολή, για παράδειγμα να χρησιμοποιήσουμε την rm
με ορίσματα πολλά ονόματα αρχείων:
rm file1.c file2.c file3.c file4.c
Ομοίως, μπορούμε να αντιγράψουμε πολλά αρχεία με μια εντολή:
cp file1.c file2.c file3.c file4.c /media/USB_STICK
Σε αυτή τη περίπτωση, το τελευταίο όρισμα στην εντολή cp
πρέπει να είναι ένας κατάλογος που υπάρχει.
Με τον ίδιο τρόπο, θα μπορούσαμε να χρησιμοποιήσουμε κάποια άλλη εντολή
που θα εφαρμόσει κάποια ενέργεια σε πολλά αρχεία.
Φανταστείτε, όμως, να θέλουμε να αντιγράψουμε εκατό αρχεία. Ακόμη και αν χρησιμοποιήσουμε τη δυνατότητα του κελύφους για αυτόματη συμπλήρωση ονόματος αρχείου, θα ήταν αδύνατο να πληκτρολογήσουμε εκατό ονόματα αρχείων.
Αν όλα τα αρχεία που θέλουμε να διαγράψουμε ή αντιγράψουμε ή μετακινήσουμε έχουν κάποιο κοινό χαρακτηριστικό, τότε μπορούμε να χρησιμοποιήσουμε τους χαρακτήρες μπαλαντέρ, για να αναφερθούμε σε αυτά, χωρίς να γράφουμε όλα τα ονόματα.
Οι χαρακτήρες μπαλαντέρ (wildcard characters) [] συνοψίζονται στον παρακάτω πίνακα:
Σύμβολο | Εξήγηση |
---|---|
* | Σημαίνει οποιοσδήποτε συνδυασμός χαρακτήρων οποιουδήποτε μήκους (ακόμη και μηδενικού μήκους) |
? | Σημαίνει ένας ακριβώς χαρακτήρας – οποιοσδήποτε χαρακτήρας |
[xyz] | Σημαίνει ένας ακριβώς χαρακτήρας από το σύνολο των χαρακτήρων που αναγράφονται μέσα στις αγκύλες: ("x", "y", "z" ) |
[^xyz] | Σημαίνει ένας ακριβώς χαρακτήρας – οποιοσδήποτε χαρακτήρας εκτός των ("x", "y", "z" ). Το σύμβολο "^" αμέσως μετά την αγκύλη "[" δηλώνει άρνηση. |
[!xyz] | Εναλλακτικά του "^" μπορεί να χρησιμοποιηθεί και το "!". Δηλώνει άρνηση. |
[abcdxyz] [a-dxyz] [a-dx-z] |
Εάν οι χαρακτήρες του συνόλου που δηλώνουμε είναι συνεχόμενοι στον πίνακα χαρακτήρων, τότε μπορεί να χρησιμοποιηθεί η παύλα "-" για να δηλώσει "από - έως". Οι τρεις εκφράσεις είναι ισοδύναμες. |
[!a-dxyz] | Μπορεί να γίνει συνδυασμός του εύρους ("-") με την άρνηση. Το παράδειγμα σημαίνει ένας οποιοσδήποτε χαρακτήρας, αλλά όχι κάποιος από τους ("a", "b", "c", "d", "x", "y", "z"). |
Επίσης, υπάρχουν και αρκετές συντομεύσεις σε κάποια συχνά χρησιμοποιούμενα σύνολα χαρακτήρων. Για παράδειγμα η συντόμευση [:upper:] σημαίνει ένα οποιοδήποτε κεφαλαίο γράμμα και μπορεί να χρησιμοποιηθεί μέσα σε ακόμη ένα ζευγάρι αγκυλών: [[:upper:]]. Παραδείγματα:
ls [[:upper:]]* # θα εμφανίσει τα ονόματα αρχείων/καταλόγων # που ξεκινούν με κεφαλαίο γράμμα. ls [[:upper:]156]* # θα εμφανίσει τα ονόματα αρχείων/καταλόγων # που ξεκινούν με κεφαλαίο γράμμα ή "1" ή "5" ή "6". ls [![:upper:]]* # θα εμφανίσει τα ονόματα αρχείων # που δεν ξεκινούν με κεφαλαίο γράμμα. ls [![:upper:]ad]* # θα εμφανίσει τα ονόματα αρχείων # που δεν ξεκινούν ούτε με # κεφαλαίο γράμμα ούτε με τα γράμματα "a", "d".
Στον παρουσιάζονται οι περισσότερο συχνές συντομεύσεις:
Σύμβολο | Εξήγηση |
---|---|
[:alnum:] | αλφαριθμητικός χαρακτήρας |
[:alpha:] | αλφαβητικός χαρακτήρας |
[:upper:] | αλφαβητικός κεφαλαίος χαρακτήρας |
[:lower:] | αλφαβητικός πεζός χαρακτήρας |
[:digit:] | χαρακτήρας δεκαδικού αριθμού, δηλαδή 0-9 |
[:xdigit:] | χαρακτήρας δεκαεξαδικού αριθμού, δηλαδή 0-9abcdef ή και κεφαλαία. |
[:space:] | χαρακτήρας που αντιστοιχεί σε διάστημα: κενό διάστημα (space), στηλοθέτης (tab), αλλαγή γραμμής (Enter) και παρόμοιους |
[:print:] | Όλοι οι εκτυπώσιμοι χαρακτήρες. |
[:graph:] | Όλοι οι εκτυπώσιμοι χαρακτήρες εκτός των [:space:] |
[:cntrl:] | Όλοι οι χαρακτήρες ελέγχου, δηλαδή μη εκτυπώσιμοι. |
[:punct:] | Χαρακτήρες στίξης. |
Όπως είναι γνωστό, τα δεδομένα αποθηκεύονται σε bytes. Όταν αποθηκεύεται ένα αρχείο με κείμενο, τότε ο κάθε χαρακτήρας αντιστοιχεί σε ένα byte, δηλαδή σε έναν αριθμό από 0 έως 255. Αυτή η αντιστοιχία χαρακτήρα με byte ονομάζεται σύνολο χαρακτήρων (character set ή συντομογραφικά charset).
Στο κέλυφος, όταν χρησιμοποιούμε μια κλάση χαρακτήρων της μορφής [A-Z], για τη σύγκριση των χαρακτήρων χρησιμοποιούνται οι κανόνες σύγκρισης χαρακτήρων που ορίζονται από το σύνολο χαρακτήρων (character set) που χρησιμοποιείται. Τα βασικά σύνολα χαρακτήρων είναι τα: ASCII, ISO8859-1, ISO8859-2, ... ISO8859-16, UTF8, UTF16, κτλ. ASCII
Ένα από τα πρώτα σύνολα χαρακτήρων και η βάση για πολλά επόμενα είναι το σύνολο ASCII (American Standard Code for Information Interchange). Το ASCII έγινε πρότυπο από τον οργανισμό ISO (International Organization for Standardization) τη δεκαετία του 1960 ως ISO-646. Σε αυτό το σύνολο χαρακτήρων χρησιμοποιούνται 7bits για την αναπαράσταση του κάθε χαρακτήρα. Υπάρχουν 128 χαρακτήρες, οι πρώτοι 32 είναι χαρακτήρες ελέγχου και οι υπόλοιποι είναι εκτυπώσιμοι (αριθμοί, τα γράμματα του αγγλικού αλφαβήτου, σημεία στίξης και κάποια σύμβολα.
30 40 50 60 70 80 90 100 110 120 ---------------------------------- 0: ( 2 < F P Z d n x 1: ) 3 = G Q [ e o y 2: * 4 > H R \ f p z 3: ! + 5 ? I S ] g q { 4: " , 6 @ J T ^ h r | 5: # - 7 A K U _ i s } 6: $ . 8 B L V ` j t ~ 7: % / 9 C M W a k u DEL 8: & 0 : D N X b l v 9: ´ 1 ; E O Y c m w |
Στον παρουσιάζονται οι εκτυπώσιμοι χαρακτήρες του συνόλου ASCII και η αντιστοιχία τους. Οι πρώτοι 32 χαρακτήρες (0-31) του πίνακα (και ο 127) περιέχουν χαρακτήρες ελέγχου. Οι χαρακτήρες ελέγχου δεν φαίνονται, αλλά δίνουν κάποια πληροφορία (συνήθως στο τερματικό που τους ερμηνεύει). Παράδειγμα, ο χαρακτήρας που αντιστοιχεί στο 7 οδηγεί το τερματικό να κάνει ήχο (bell συμβολίζεται ως BEL, \a, ^G), ο 10 αντιστοιχεί στην αλλαγή γραμμής (line feed: συμβολίζεται ως LF, \n, ^J) κτλ. Στον παραπάνω πίνακα εμφανίζονται μόνο οι εκτυπώσιμοι χαρακτήρες, βλέπουμε για παράδειγμα ότι το "Α" αντιστοιχεί στον αριθμό 65, το "i" στον αριθμό 105 κτλ.
Η σειρά με την οποία εκφράζεται ένα εύρος χαρακτήρων ορίζεται από τη σειρά των χαρακτήρων στον πίνακα ASCII ή στο σύνολο χαρακτήρων που χρησιμοποιείται.
Έτσι αν δώσουμε:
ls [5-T]*
το [5-Τ] σημαίνει ένας χαρακτήρας μέσα στο εύρος από το χαρακτήρα "5" μέχρι τον "Τ". Ποιο είναι αυτό το εύρος; Θα είναι οι χαρακτήρες 5 6 7 8 9 : ; < = > ? @ A...Τ.
Εδώ, πρέπει να παρατηρήσουμε ότι το σύνολο ASCII ορίζει 128 χαρακτήρες. Άρα, χρησιμοποιεί 7 bits. Το όγδοο bit συνήθως χρησιμοποιούνταν ως bit ελέγχου (parity bit).
ISO-8859-1 ISO-8859-7Αυτοί οι 128 χαρακτήρες, που στην πραγματικότητα ήταν 95, αν εξαιρέσουμε τους χαρακτήρες ελέγχου, ήταν αρκετοί για τον συμβολισμό των αγγλικών γραμμάτων, όχι όμως και για γράμματα άλλων γλωσσών. Επιπλέον, τη δεκαετία του 1990 είχαν βελτιωθεί αρκετά τα μέσα αποθήκευσης και επικοινωνίας και δεν απαιτούνταν η χρήση του bit ελέγχου. Τότε ορίστηκαν τα σύνολα χαρακτήρων ISO-8859, κατά τα οποία χρησιμοποιούνταν 8bits για την αναπαράσταση ενός χαρακτήρα, δηλαδή υπήρχαν 256 διαθέσιμοι χαρακτήρες.
Παρόλα αυτά, οι 256 διαθέσιμες θέσεις χαρακτήρων δεν αρκούν για τον συμβολισμό όλων των γραμμάτων όλων των γλωσσών. Έτσι, ο οργανισμός ISO όρισε τα υποσύνολα: ISO-8859-1, ISO-8859-2, ... ISO-8859-16. Σε όλα αυτά τα σύνολα, οι πρώτοι 128 χαρακτήρες είναι ίδιοι με το ASCII. Οι υπόλοιποι χαρακτήρες ορίζονται για τα σύμβολα της χώρας που χρησιμοποιούνται. Το ISO-8859-1 [ref] αντιστοιχεί στα αγγλικά () ενώ το ISO-8859-7[ref] περιέχει τους ελληνικούς χαρακτήρες ().
Ο ορισμός των ISO-8859 και ιδιαίτερα του ISO-8859-7 υποτίθεται ότι θα έδινε ένα τέλος στη χρήση των greeklish σε ελληνικά (ανεπίσημα συνήθως) κείμενα. Όμως, στην πραγματικότητα δημιούργησε ακόμη περισσότερα προβλήματα. Ένας χρήστης (ή το σύστημα) θα έπρεπε να γνωρίζει το σύνολο χαρακτήρων που χρησιμοποιεί ένα κείμενο για να μπορέσει να το προβάλει σωστά. Έτσι, έχοντας ένα κείμενο γραμμένο με ISO-8859-7, αν στην προβολή του δεν λαμβάνονταν αυτό υπόψη και χρησιμοποιούνταν το ISO-8859-1 (που είναι το πλέον συχνό παγκοσμίως), τότε το κείμενο δεν είναι αναγνώσιμο. Παράδειγμα (όπως φαίνεται στα 2 Σχήματα), ο χαρακτήρας "β" θα εμφανίζεται ως "â", ενώ ο χαρακτήρας "Π" σαν "Ð" κ.ο.κ. UTF
Ήταν προφανής η ανάγκη για ορισμό ενός συνόλου χαρακτήρων με βάση το οποίο δεν θα υπήρχε διφορούμενο byte. Έτσι, ορίστηκαν τα multi-byte character sets και η οικογένεια UTF. Σε αυτά τα σύνολα χαρακτήρων για την αναπαράσταση ενός χαρακτήρα χρησιμοποιούνται πάνω από ένα bytes. Συνεπώς, οι δυνατοί συνδυασμοί είναι πολλοί και ικανοί να αναπαραστήσουν πολλούς χαρακτήρες. Στο UTF-8 ένας χαρακτήρας καταλαμβάνει από 8 έως 16 bits (1 - 2 bytes). Οι πρώτοι 128 χαρακτήρες είναι ίδιοι με το ASCII. Στο UTF-16 ένας χαρακτήρας καταλαμβάνει 16 ή 32 bits (2 - 4 bytes).
Στο Linux, χρησιμοποιείται πλέον ως προκαθορισμένο σύνολο χαρακτήρων το UTF-8. Επίσης, στον Παγκόσμιο Ιστό (WWW) χρησιμοποιείται κυρίως το UTF-8. Παρόλα αυτά, δεδομένης της ύπαρξης πολλών συνόλων που έχουν οριστεί από τον οργανισμό ISO και δεδομένου ότι η Microsoft έχει ορίσει τα δικά της σύνολα χαρακτήρων (windows-1252, windows-1253, κ.α.), εξακολουθεί να υπάρχει σύγχυση σε πολλές περιπτώσεις αναγνώρισης των χαρακτήρων. Απαιτείται ιδιαίτερη προσοχή, ιδίως κατά τη διαχείριση αρχείων που δημιουργήθηκαν σε διαφορετικό υπολογιστή, ο οποίος πιθανόν χρησιμοποιεί διαφορετικό προκαθορισμένο σύνολο χαρακτήρων.
Στα σύνθετα σύνολα χαρακτήρων (UTF), ορίζονται και ισοδυναμίες χαρακτήρων.
Παράδειγμα το "α" είναι ισοδύναμο με το "ά", με το "Α" και με το "Ά".
Για κάποια άλλη γλώσσα: "à" ⇔ "á" ⇔ "â" ⇔ "ã" ⇔ "ä" ⇔ "å".
|
Έτσι, το [Α-Ζ]
ταιριάζει και τους πεζούς χαρακτήρες (a-z) εφόσον χρησιμοποιείται UTF σύνολο χαρακτήρων. Συνεπώς, είναι προτιμότερο να χρησιμοποιούνται οι συντομεύσεις, όπου αυτό είναι εφικτό.
Επίσης, για παράδειγμα η συντόμευση [[:upper:]]
υπερτερεί από τη διατύπωση [Α-Ζ]
, διότι το πρώτο θα ταιριάξει σε όλους τους κεφαλαίους χαρακτήρες είτε ελληνικούς, είτε αγγλικούς, είτε τονισμένους ελληνικούς.
Μέσα σε ένα κέλυφος μπορούμε να αλλάξουμε το σύνολο χαρακτήρων που χρησιμοποιείται ορίζοντας τη μεταβλητή περιβάλλοντος LC_ALL
. Περισσότερα για τις μεταβλητές περιβάλλοντος θα δούμε στο Κεφάλαιο χχχ. Στον παραθέτουμε μόνο τον τρόπο χωρίς περαιτέρω εξήγηση []:
Απαιτείται προσοχή όταν αλλάζουμε τις ρυθμίσεις του συνόλου χαρακτήρων. Δεν αρκεί να ορίσουμε στο κέλυφος ποιο είναι το σύνολο χαρακτήρων που χρησιμοποιούμε, αλλά και στην εφαρμογή τερματικού. Στο φαίνεται μια τέτοια περίπτωση. Στην αριστερή εικόνα το τερματικό εμφανίζει "ISO-8859-7", αλλά το κέλυφος χρησιμοποιεί το UTF-8. Θα πρέπει να ενημερωθεί η πληροφορία αυτή και στην εφαρμογή τερματικού.
Αντίστοιχη ρύθμιση απαιτείται να γίνει σε όλα τα προγράμματα προσομοίωσης τερματικού είτε στο Linux, είτε στα Windows. Παράδειγμα, το putty.exe που είναι πρόγραμμα προσομοίωσης τερματικού και ssh client, αν και λειτουργεί σε Microsoft Windows, απαιτεί αντίστοιχη ρύθμιση ().
Έστω ότι στον τρέχοντα κατάλογο εργασίας υπάρχουν τα αρχεία: file1.c, file2.c, file3.c, file4.c, file5.c, file8.c, file3.h, file4.h, file2.out, test.c. Εάν θέλουμε να αντιγράψουμε τα αρχεία που το όνομά τους ξεκινά από f σε έναν άλλον κατάλογο, μπορούμε να δώσουμε την εντολή:
cp f* /media/USB_STICK
Εάν θέλουμε να αντιγράψουμε όλα τα αρχεία με την κατάληξη .c και την κατάληξη .h:
cp *.[ch] /media/USB_STICK
Εδώ πρέπει να σημειωθεί ότι:
Οι χαρακτήρες μπαλαντέρ του κελύφους (shell wildcards) ερμηνεύονται από το κέλυφος και είναι ανεξάρτητοι της εντολής που χρησιμοποιείται. Άρα, μπορούν να χρησιμοποιηθούν με οποιαδήποτε εντολή, με τον ίδιο τρόπο. |
Στα παρακάτω παραδείγματα χρησιμοποιούνται μπαλαντέρ με τις εντολές ls
και echo
.
asidirop@aetos:~/tmp/os_wild$ ls -l *.c -rw------- 2 asidirop conit 0 2008-10-01 10:15 file1.c -rw------- 2 asidirop conit 0 2008-10-01 10:15 file2.c -rw------- 2 asidirop conit 0 2008-10-01 10:15 file3.c -rw------- 2 asidirop conit 0 2008-10-01 10:15 file4.c -rw------- 2 asidirop conit 0 2008-10-01 10:15 file5.c -rw------- 2 asidirop conit 0 2008-10-01 10:15 file8.c -rw------- 2 asidirop conit 0 2008-10-01 10:15 test.c asidirop@aetos:~/tmp/os_wild$ echo *.h file3.h file4.h asidirop@aetos:~/tmp/os_wild$ echo The .h files in cwd are: *.h The .h files in cwd are: file3.h file4.h
Στην πρώτη εντολή, δίνουμε ως όρισμα στην ls όλα τα αρχεία των οποίων η κατάληξη είναι ".c". Στη δεύτερη εντολή, δίνονται ως όρισμα όλα τα ονόματα αρχείων των οποίων η κατάληξη είναι ".h". Η εντολή echo απλά εμφανίζει τα ορίσματα που της δόθηκαν, συνεπώς, απλά εμφανίζονται τα ονόματα αρχείων που ταίριαξαν στο μπαλαντέρ. Η τρίτη εντολή χρησιμοποιεί το ίδιο μπαλαντέρ με τη δεύτερη. Η διαφορά με την προηγούμενη είναι ότι δίνονται στην echo και άλλα ορίσματα (λέξεις). Η εντολή echo προφανώς θα εμφανίσει όλα τα ορίσματα που της δόθηκαν, και επομένως το αποτέλεσμά της θα είναι το "The .h files in cwd are: file3.h file4.h".
Microsoft Power Shell MS-DOSΣε αντίθεση με το UNIX, το DOS δεν υποστηρίζει χαρακτήρες μπαλαντέρ (wildcards). Σε μερικές εντολές, όμως, χρησιμοποιούνται (πχ. dir *.exe). H ερμηνεία τους εξαρτάται από την κάθε εντολή. Στο προηγούμενο παράδειγμα η εντολή dir ερμήνευσε το *. | |
Στα Microsoft Windows υπάρχει η δυνατότητα χρήσης μπαλαντέρ κατά την αναζήτηση αρχείων μέσα από τον διαχειριστή αρχείων, καθώς επίσης και από το Microsoft Power Shell. |
Κατά τη χρήση μιας αναφοράς σε αρχείο με μπαλαντέρ, εάν δεν βρεθεί αντιστοιχία με κάποιο όνομα αρχείου, τότε οι χαρακτήρες μπαλαντέρ (wildcards) δεν «μεταφράζονται» από το κέλυφος. Στο παρακάτω παράδειγμα, η πρώτη εντολή περιλαμβάνει το "*.x". Δεν βρίσκεται, όμως, κάποιο αρχείο με αυτό το όνομα. Συνεπώς, το κέλυφος δεν μπορεί να αντικαταστήσει το
μπαλαντέρ με κάτι άλλο και το "*.x" παραμένει όπως είναι. Η εντολή echo
θα λάβει ως όρισμα τη συμβολοσειρά "*.x" και απλά θα την εκτυπώσει. Δεν θα εμφανιστεί κανένα μήνυμα σφάλματος. Αντιθέτως, στην τελευταία εντολή που χρησιμοποιείται πάλι το "*.x", η εντολή θα εμφανίσει μήνυμα σφάλματος. Αυτό συμβαίνει διότι η εντολή cp θα λάβει ως πρώτο όρισμα το "*.x" και θα ψάξει να βρει το αρχείο με αυτό το όνομα για να το αντιγράψει. Δεν θα βρει αρχείο με όνομα "*.x" και άρα, θα μας ενημερώσει για το σφάλμα.
asidirop@aetos:~/tmp/os_wild$ echo *.x *.x asidirop@aetos:~/tmp/os_wild$ echo *.c file1.c file2.c file3.c file4.c file5.c file8.c test.c asidirop@aetos:~/tmp/os_wild$ cp *.c /tmp asidirop@aetos:~/tmp/os_wild$ cp *.x /tmp cp: cannot stat `*.x': No such file or directory
Ακόμη ένα παράδειγμα στο οποίο μοιάζουν οι εντολές να μην έχουν ντετερμινιστική συμπεριφορά είναι το παρακάτω:
Έστω ότι σε έναν φάκελο περιέχονται τα αρχεία "a" και "b" τα οποία θέλουμε να τα αντιγράψουμε κάπου αλλού. Η εντολή
για να αντιγράψουμε όλα τα αρχεία στον φάκελο /tmp
είναι η "cp * /tmp"
.
Έστω, όμως, ότι κατά την πληκτρολόγησή της πατήσαμε "Enter" πριν από το /tmp
. Άρα, γράψαμε την εντολή "cp *"
.
Παραδόξως ούτε το κέλυφος εμφανίζει κάποιο μήνυμα σφάλματος, αλλά ούτε και η εντολή cp
παρόλο που παραλείψαμε τον φάκελο προορισμού. Τι συνέβη;
asidirop@aetos:~/tmp/os_wild2$ ls -l total 8 -rw------- 1 asidirop conit 12 2008-10-01 10:34 a -rw------- 1 asidirop conit 24 2008-10-01 10:34 b asidirop@aetos:~/tmp/os_wild2$ cp * /tmp asidirop@aetos:~/tmp/os_wild2$ cp * asidirop@aetos:~/tmp/os_wild2$Δίνοντας την εντολή
"cp *"
, το "*" μεταφράζεται στα ονόματα αρχείων του τρέχοντος καταλόγου, δηλαδή σε "a b"
.
Συνεπώς, η εντολή που εκτελέστηκε ήταν η:
cp a b
Η παραπάνω εντολή δεν αντιστοιχεί στην αντιγραφή του "a" και "b" σε έναν φάκελο προορισμού, αλλά στην αντιγραφή του "a" επάνω στο "b". Έτσι, το αρχείο "b" αντικαθίσταται από το "a".
Εάν στον ίδιο κατάλογο είχαμε τρία αρχεία (αντί δυο), έστω τα "a", "b" και "c", τότε το αποτέλεσμα της ίδιας εντολής θα ήταν διαφορετικό
asidirop@aetos:~/tmp/os_wild2$ ls -l total 12 -rw------- 2 asidirop conit 12 2008-10-01 10:34 a -rw------- 2 asidirop conit 12 2008-10-01 10:35 b -rw------- 1 asidirop conit 38 2008-10-01 10:40 c asidirop@aetos:~/tmp/os_wild2$ cp * cp: target `c' is not a directory
Γιατί, σε αυτήν την περίπτωση, εμφανίζεται μήνυμα σφάλματος και δεν γίνεται αντιγραφή όπως πριν; Ο χειρισμός από το κέλυφος παραμένει ο ίδιος. Αντικαθιστά το "*" με τα ονόματα αρχείων που ταιριάζουν. Σε αυτήν την περίπτωση, τα "a", "b" και "c". Συνεπώς, η εντολή μεταφράζεται σε:
cp a b c
Όταν δίνονται στην εντολή cp
πάνω από δυο ορίσματα, τότε τα πρώτα ν-1 είναι αρχεία πηγής και το τελευταίο πρέπει να είναι κατάλογος προορισμού, ώστε να αντιγράψει όλα τα αρχεία πηγή μέσα στον κατάλογο. Όμως, το "c" είναι αρχείο και όχι κατάλογος. Η εντολή cp δεν μπορεί να αντιγράψει δυο αρχεία σε ένα τρίτο και εμφανίζει μήνυμα σφάλματος ότι ο προορισμός "c" δεν είναι κατάλογος.
Εάν κατά τύχη, στον τρέχοντα κατάλογο υπήρχε και υποκατάλογος, του οποίου το όνομα έπονταν αλφαβητικά των ονομάτων όλων των αρχείων, παράδειγμα αρχεία με ονόματα "a", "b", "c" και ένας κατάλογος με όνομα "z", τότε η συμπεριφορά της ίδιας εντολής θα ήταν πάλι διαφορετική:
asidirop@aetos:~/tmp/os_wild2$ ls -l total 12 -rw------- 2 asidirop conit 12 2008-10-01 10:34 a -rw------- 2 asidirop conit 12 2008-10-01 10:35 b -rw------- 1 asidirop conit 38 2008-10-01 10:40 c drwx------ 2 asidirop conit 6 2008-10-01 10:43 z asidirop@aetos:~/tmp/os_wild2$ cp * asidirop@aetos:~/tmp/os_wild2$ ls -l total 12 -rw------- 2 asidirop conit 12 2008-10-01 10:34 a -rw------- 2 asidirop conit 12 2008-10-01 10:35 b -rw------- 1 asidirop conit 38 2008-10-01 10:40 c drwx------ 2 asidirop conit 30 2008-10-01 10:44 z asidirop@aetos:~/tmp/os_wild2$ ls -l z/ total 12 -rw------- 1 asidirop conit 12 2008-10-01 10:44 a -rw------- 1 asidirop conit 12 2008-10-01 10:44 b -rw------- 1 asidirop conit 38 2008-10-01 10:44 c
Δίνοντας cp *, ουσιαστικά η εντολή μεταφράστηκε σε
cp a b c z
το οποίο σημαίνει: «αντίγραψε τα αρχεία "a", "b" και "c" στον κατάλογο "z"».
Έστω ότι σε έναν κατάλογο υπάρχουν τα αρχεία:
file1.txt, file2.txt, file9.txt, file10.txt, file15.txt, file20.txt, file30.txt
και θέλουμε να αντιγράψουμε τα αρχεία με τους αριθμούς από 10 έως και 30, αλλά όχι τα file1.txt , file2.txt, file9.txt.
Ένα συνηθισμένο σφάλμα είναι να χρησιμοποιήσουμε την έκφραση: file[10-30].txt, για παράδειγμα cp file[10-30].txt /tmp
.
Μέσα στις αγκύλες ορίζονται χαρακτήρες και όχι αριθμοί. |
Συνεπώς, το [10-30]
θα ερμηνευτεί από το κέλυφος ως οι χαρακτήρες: "1","0"-"3","0"
,
δηλαδή οι χαρακτήρες ("1", "0", "1", "2", "3", "0"
).
Συνεπώς, η προηγούμενη εντολή θα αντιγράψει τα αρχεία file1.txt και file2.txt που είναι αυτά
τα οποία δεν θέλαμε να αντιγράψουμε.
Ένας σωστός τρόπος για να αναφερθούμε στα αρχεία file10.txt, file15.txt, file20.txt, file30.txt είναι:
cp file[12][0-9].txt file30.txt /tmp
Το [12][0-9]
σημαίνει να υπάρχει είτε το "1", είτε το "2" και μετά ακόμη ένας αριθμός από "0" έως "9".
Με αυτόν τον τρόπο καλύπτονται οι συνδυασμοί 10, 11, 12, ..., 19, 20, 21,...,29.
Αυτό που δεν καλύπτεται είναι το "30", το οποίο και πρέπει να το αναφέρουμε ξεχωριστά.
Αν χρησιμοποιούσαμε το file[123][0-9].txt, τότε θα καλύπταμε τους συνδυασμούς 10-39 που είναι έξω από τα όρια που θα θέλαμε.
ΕισαγωγικάΤο κέλυφος δεν ερμηνεύει τους χαρακτήρες μπαλαντέρ, όταν αυτοί βρίσκονται μέσα σε εισαγωγικά, είτε μονά (') είτε διπλά ("). Περισσότερα για την χρήση των εισαγωγικών και την σημασία τους θα πούμε στο . Στο παρακάτω παράδειγμα, στην πρώτη εντολή, το *.h ερμηνεύεται από το κέλυφος και αντικαθίσταται με τα ονόματα αρχείων που ταιριάζει. Στις δυο επόμενες, όμως, επειδή βρίσκεται μέσα σε εισαγωγικά, δεν ερμηνεύεται και παραμένει ως έχει.
asidirop@aetos:~/tmp/os_wild$ echo The .h files in cwd are: *.h The .h files in cwd are: file3.h file4.h asidirop@aetos:~/tmp/os_wild$ echo "The .h files in cwd are: *.h" The .h files in cwd are: *.h asidirop@aetos:~/tmp/os_wild$ echo 'The .h files in cwd are: *.h' The .h files in cwd are: *.h asidirop@aetos:~/tmp/os_wild$ ls –l "*.c" ls: cannot access *.c: No such file or directory
Με τη χρήση της echo
, η μη ερμηνεία του μπαλαντέρ δεν οδηγεί σε κάποιο πρόβλημα. Απλά εκτυπώνεται στην οθόνη.
Με την χρήση της ls
, όμως, (τέταρτη εντολή) η μη ερμηνεία του, οδηγεί την ls
να εμφανίσει μήνυμα σφάλματος. Αυτό διότι στην ls
δεν περνούν ως ορίσματα τα ονόματα αρχείων, αλλά περνάει ως όρισμα η συμβολοσειρά "*.c"
.
H ls
ψάχνει να βρει ένα αρχείο με αυτό το όνομα. Δεν βρίσκει κάποιο και συνεπώς εμφανίζει μήνυμα σφάλματος.
Εάν στον τρέχοντα κατάλογο υπήρχε αρχείο με το όνομα "*.c", τότε η ls
θα εμφάνιζε πληροφορίες για αυτό το αρχείο.
Οι χαρακτήρες μπαλαντέρ μπορούν να αποτελέσουν και τμήμα μιας διαδρομής. Έτσι μπορούμε να αναφερθούμε σε αρχεία που βρίσκονται σε διαφορετικούς φακέλους:
asidirop@aetos:~/tmp/os_wild$ echo ~/t*
/home/staff/ektaktoi/asidirop/tcp3.txt /home/staff/ektaktoi/asidirop/test /home/staff/ektaktoi/asidirop/tests /home/staff/ektaktoi/asidirop/tmp /home/staff/ektaktoi/asidirop/ttt
Για την παραπάνω εντολή το κέλυφος, πρώτα θα ερμηνεύσει τον ειδικό χαρακτήρα "~"
(βλέπε )
και μετά θα τον αντικαταστήσει με το /home/staff/ektaktoi/asidirop
. Έπειτα, θα δημιουργηθεί η έκφραση
/home/staff/ektaktoi/asidirop/t* σύμφωνα με την οποία θα αναζητήσει για αρχεία των οποίων το όνομα ξεκινά από "t" μέσα στον συγκεκριμένο φάκελο. Εφόσον βρει τα αρχεία "tcp3.txt", "test", "tests", "tmp", "ttt"
θα αντικαταστήσει το "t*" με τα ονόματα αρχείων, βάζοντας, όμως, πριν από το καθένα και τη Διαδρομή που είχε χρησιμοποιηθεί. Έτσι η διαδρομή επαναλαμβάνεται για κάθε αρχείο.
Με τον ίδιο τρόπο συμπεριφέρεται το κέλυφος και όταν χρησιμοποιούνται σχετικές διαδρομές. Όπως φαίνεται στο παρακάτω παράδειγμα, η διαδρομή "../../" θα επαναληφθεί για κάθε αρχείο. Μάλιστα, θα επαναληφθεί ως σχετική διαδρομή, όπως ακριβώς διατυπώθηκε στην εντολή.
asidirop@aetos:~/tmp/os_wild$ echo ../../t* ../../tcp3.txt ../../test ../../tests ../../tmp ../../ttt asidirop@aetos:~/tmp/os_wild$ echo ../../t* ../ο* ../../tcp3.txt ../../test ../../tests ../../tmp ../../ttt ../os_wild
Προφανώς, μέσα στην ίδια εντολή, μπορεί να γίνει χρήση πολλών εκφράσεων με μπαλαντέρ όπως στη δεύτερη εντολή του προηγούμενου παραδείγματος.
Η χρήση των χαρακτήρων μπαλαντέρ αποκτά ακόμη μεγαλύτερο ενδιαφέρον, όταν χρησιμοποιούνται για να δημιουργήσουν διαδρομές.
asidirop@aetos:~/tmp/os_wild$ echo /*/*/*cnf /etc/mysql/debian.cnf /etc/mysql/my.cnf /etc/ssl/openssl.cnf asidirop@aetos:~/tmp/os_wild$ echo /*/m*/*cnf /etc/mysql/debian.cnf /etc/mysql/my.cnf
Στην πρώτη εντολή του παραδείγματος, χρησιμοποιούμε το "*" ως τμήμα Διαδρομής που σημαίνει οποιοδήποτε τμήμα μονοπατιού. Η συγκεκριμένη εντολή πρακτικά θα μας δώσει όλα τα ονόματα αρχείων που τελειώνουν σε "cnf" και βρίσκονται δυο επίπεδα μακριά από τη ρίζα του συστήματος αρχείων (root directory). Έτσι, εμφανίζονται τα "debian.cnf", "my.cnf" και "openssl.cnf" τα οποία, όμως, βρίσκονται σε διαφορετικούς καταλόγους. Όλοι οι κατάλογοι, όμως, βρίσκονται σε απόσταση δυο επιπέδων από τη ρίζα. Προφανώς, το κέλυφος εμφανίζει τις διαδρομές οι οποίες παρήχθησαν.
Στη δεύτερη εντολή του παραδείγματος, δημιουργούμε παρόμοιες διαδρομές, μόνο που επιπλέον υπάρχει ο περιορισμός ότι το δεύτερο τμήμα μονοπατιού ξεκινά από 'm". Έτσι, δεν θα παραχθεί η διαδρομή "/etc/ssl/openssl.cnf", της οποίας το δεύτερο τμήμα στο μονοπάτι δεν ξεκινά από "m", αλλά μόνο οι διαδρομές "/etc/mysql/debian.cnf" και "/etc/mysql/my.cnf".
Εξοικείωση με τον χειρισμό αρχείων και καταλόγων με χαρακτήρες μπαλαντέρ.
Δημιουργήστε στον τρέχοντα κατάλογο τα παρακάτω αρχεία:
hello.dat hello.doc hello.exe hello1.exe hello2.exe Hello.dat Hello.exe hello12.c helloA.exe helloAexe hello10.exe
Μπορείτε να τα δημιουργήσετε όλα μαζί χρησιμοποιώντας την εντολή:
touch hello.dat hello.doc hello.exe hello1.exe hello2.exe Hello.dat Hello.exe helloA.exe helloAexe hello10.exe hello12.c
Να βρείτε και να εξηγήσετε τα αποτελέσματα των εντολών :
Δημιουργήστε ένα sub-directory κάτω από το home directory σας με όνομα της επιλογής σας. Στη συνέχεια μέσα σε αυτό το sub-directory δημιουργήστε με την εντολή touch τα παρακάτω αρχεία:
Feb96 jan12.02 jan19.02 jan26.02 jan5.02 Jan95 jan96 jan97 jan98 mar98 memo1 memo10 memo2 memo2.sv memo4
Να βρείτε το αποτέλεσμα των παρακάτω εντολών :
ls *
ls *[!0-9]
ls m[a-df-z]*
ls [A-Z]*
ls jan*
ls *.*
ls ?????
ls *02
ls jan?? feb?? mar??
ls [fjm][ae][bnr]*
echo jan*
ls –l jan*
echo january*
ls –l january*
Χρησιμοποιώντας μπαλαντέρ εμφανίστε τα αρχεία (με την ls) που το όνομά τους ξεκινάει με "memo" και στη συνέχεια έχουν έναν αριθμό από το 3 έως το 20 (άρα, θέλουμε να εμφανιστούν τα ονόματα memo4, memo10).
Θεωρήστε τα αρχεία που υπάρχουν στη 3η στήλη του παρακάτω πίνακα. Ποια από τα ονόματα αυτά αντιστοιχούν στην αντίστοιχη έκφραση που υπάρχει στην 2η στήλη;
A/A | Έκφραση με μπαλαντέρ | Αρχεία που υπάρχουν στον τρέχοντα κατάλογο |
---|---|---|
1 | gn*.1 | gnu.1, gn.1, gneiss.1, gn/x.1 |
2 | [A-Z]*[!0-9] | A2q, Maria, George, baggelis, Bag10 |
3 | *.[acAC] | File.a, file.C, .a, .file. |
4 | */doit* | one/doit, three/doit.h, two/doit.c, doit |
Δημιουργήστε τα παραπάνω αρχεία σε καταλόγους της επιλογής σας και ελέγξτε ποια από αυτά θα αντιστοιχηθούν σε κάθε έκφραση χρησιμοποιώντας την εντολή echo. Στην περίπτωση (4) για το one/doit εννοείται ότι το αρχείο doit βρίσκεται σε έναν κατάλογο με το όνομα "one" (O κατάλογος "one" βρίσκεται στον τρέχοντα). Αντίστοιχα και οι υπόλοιποι:
. ├── gn │ └── x.1 ├── gn.1 ├── gneiss.1 └── gnu.1 |
. ├── doit ├── one │ └── doit ├── three │ └── doit.h └── two └── doit.c |
Τι παρατηρείτε στις περιπτώσεις (3) και (4) ; Είναι τα αποτελέσματα αναμενόμενα;
Σε αυτήν την άσκηση πρέπει να εργαστείτε στον aetos.it.teithe.gr με απομακρυσμένη πρόσβαση. Σε περίπτωση που δεν διαθέτετε λογαριασμό στον συγκεκριμένο υπολογιστή, κατεβάστε το αρχείο: http://aetos.it.teithe.gr/~asidirop/OSIntroBook/OSIntro.zip και αποθηκεύστε το σε έναν κατάλογο της επιλογής σας (πχ: /tmp). Μετά, δώστε τις εντολές
asidirop@antonis-PC:~$ cd /tmp asidirop@antonis-PC:/tmp$ unzip OSIntro.zip
Στην απίθανη περίπτωση που δεν είναι εγκατεστημένη η εντολή unzip, μπορείτε να την εγκαταστήσετε χρησιμοποιώντας την εφαρμογή Διαχείρισης Προγραμμάτων της διανομής που χρησιμοποιείτε. Εάν χρησιμοποιείτε debian ή κάποια παραλλαγή του (ubuntu, kali, κ.ά.), μπορείτε να κάνετε εγκατάσταση στην εντολή unzip με την εντολή:
sudo apt-get install unzip
Εναλλακτικά, μπορείτε να κατεβάσετε το αρχείο: http://aetos.it.teithe.gr/~asidirop/OSIntroBook/OSIntro.tar.gz και να το αποσυμπιέσετε με την εντολή:
asidirop@antonis-PC:~$ cd /tmp asidirop@antonis-PC:/tmp$ tar xvfz OSIntro.tar.gz
Το tar και gunzip (που είναι τα προγράμματα χειρισμού των αρχείων tar και gz) πάντα εγκαθιστώνται σε ένα σύστημα Unix/Linux, διότι αποτελούν την παραδοσιακή μέθοδο για συμπίεση και ανταλλαγή αρχείων και φακέλων.
cp *Τι συνέβη; Δεν θα έπρεπε η εντολή να μας εμφανίσει μήνυμα σφάλματος εφόσον δεν έχουμε ορίσει κατάλογο προορισμού για την αντιγραφή;
mv *Τι συνέβη; Ελέγξτε τα περιεχόμενα του καταλόγου και των αρχείων.
cp *Τι συνέβη; Ελέγξτε τα περιεχόμενα του καταλόγου και των αρχείων.