+++
title = 'Tips για την γραμμή εντολής.'
date = '2003-08-01T00:00:00Z'
description = ''
author = 'Φανουργάκης Μανώλης(mailto:mfano@NOSPAMfreemail.gr)'
issue = ['Magaz 34']
issue_weight = 4
+++

----------------------------------------------------------------------------------------------------------------------------------------------------------------

*Μερικά tips που διευκολύνουν τη ζωή μας στη γραμμή εντολής*

----------------------------------------------------------------------------------------------------------------------------------------------------------------

**1. Aliases**
-------------------------------------

-   [1.1 ls](#ss1.1)
-   [1.2 less](#ss1.2)
-   [1.3 pushd, popd, dirs](#ss1.3)
-   [1.4 PATH](#ss1.4)
-   [1.5 history](#ss1.5)
-   [1.6 find](#ss1.6)
-   [1.7 Συντόμευση για συνηθισμένα μακριά command lines.](#ss1.7)
-   [1.8 Διάφορα](#ss1.8)

**2. Shell prompt**
------------------------------------------

**3. Vi (=very intelligent) editor**
-----------------------------------------------------------

**4. Screen**
------------------------------------


### [1. Aliases]{#s1}

Τα παρακάτω aliases μπορούν να μπουν στο \~/.bashrc. Αν όμως γίνουν πολλά, είναι καλύτερα για λόγους τάξης να μπουν σε ένα ξεχωριστό αρχείο, π.χ. στο \~/.alias
και να μπει στο \~/.bashrc η γραμμή:

    test -s ~/.alias && . ~/.alias

### [1.1 ls]{#ss1.1}

    alias l='ls -lA '
    alias lh='l -h '

Ο διακόπτης -h της ls είναι αρκετά χρήσιμος γιατί μετατρέπει το μέγεθος αρχείων σε kB,MB,GB. Έτσι, με \'l \~/mbox\' θα πάρω το παρακάτω:

    -rw-------    1 manolis  users      135987 Ιούλ 28 22:33 /home/manolis/mbox

Ενώ με \'lh \~/mbox\' το παρακάτω:

    -rw-------    1 manolis  users        133k Ιούλ 28 22:33 /home/manolis/mbox

### [1.2 less]{#ss1.2}

    alias m='$PAGER'

Όπου η μεταβλητή PAGER έχει τεθεί στο \~/.bashrc ως εξής:

    export PAGER='less -rM '

Ή ό,τι άλλο χρησιμοποιείται ως pager τέλος πάντων. Εξαιρετικά βολικό, χρησιμοποιώ το less αμέτρητες φορές κάθε μέρα.

### [1.3 pushd, popd, dirs]{#ss1.3}

    alias pd='pushd'
    alias po='popd'
    alias ds='dirs -v'

Χρήσιμα για τις \...περιπλανήσεις μας στη δομή αρχείων του linux.

Οι εντολές pushd, popd, dirs χειρίζονται μια στοίβα (stack) καταλόγων στους οποίους μετακινούμαστε.

-   Με την εντολή \'pushd dir\' μεταφερόμαστε στον κατάλογο dir και τοποθετείται αυτός στην κορυφή της στοίβας.
-   Με την εντολή popd αφαιρείται ο κατάλογος που βρίσκεται στην κορυφή της στοίβας και μεταφερόμαστε σ\' αυτόν που θα γίνει η νέα κορυφή.
-   Με την εντολή dirs βλέπουμε τα περιεχόμενα της στοίβας.

Ένα παράδειγμα θα γίνει πιο εύκολα κατανοητό:

    $ pd /tmp/
    /tmp ~

Ξεκινώντας ένα νέο shell βρίσκομαι στο home directory. Κάνω push το /tmp. Παρατηρώ ότι η pushd μου αναφέρει και την κατάσταση της στοίβας: Στην κορφή βρίσκεται
το /tmp και μετά το home από όπου ξεκίνησα.

    $ pd /usr/local/bin/
    /usr/local/bin /tmp ~

Έκανα push και το /usr/local/bin. Η στοίβα τώρα έχει τρεις καταλόγους.

    $ ds
    0 /usr/local/bin
    1 /tmp
    2 ~

Ας υποθέσουμε τώρα ότι θέλω να εναλλάσομαι γρήγορα μεταξύ αυτών των καταλόγων. Με ένα pushd +n (όταν χρησιμοποιήσουμε την pushd χωρίς όρισμα, εννοείται +1) ο
κατάλογος που βρίσκεται στη θέση n πάει στην κορυφή.

    $ pd +1
    /tmp /usr/local/bin ~

Με ένα popd ξεφορτώνομαι τον κατάλογο που βρίσκεται στην κορυφή και μεταφέρομαι στον αμέσως επόμενο.

    $ po
    /usr/local/bin ~

Με τη σωστή χρήση των pushd, popd, dirs μπορούμε να κάνουμε πολύ γρήγορα πολύπλοκες δουλειές. Και μην ξεχνάτε ότι τα πλήρη ονόματα των καταλόγων μπορεί να
γίνουν πολύ μεγάλα (π.χ. /usr/X11R6/lib/X11/fonts/hellas/, \~/download/pictures/flags/greece/). Είναι πολύ βολικό να μπορεί κανείς με τρία χτυπήματα πλήκτρων να
εναλάσσεται μεταξύ τους.

Για περισσότερες πληροφορίες \'help pushd\', \'help popd\', \'help dirs\'.

Επίσης, ας μην ξεχνάμε και την εντολή \'cd -\' που μας τοποθετεί στον προηγούμενο κατάλογο (σ\' αυτόν που είμασταν πριν κάνουμε cd ή pushd/popd).

### [1.4 PATH]{#ss1.4}

    alias pt='echo $PATH|tr : \\n '
    addpath() { while test "$1" ; do PATH=${PATH}:"$1" ; shift ; done ; }

Το alias pt κάνει το εξής απλό και έξυπνο: Παίρνει τη μεταβλητή PATH και την περνάει στην εντολή tr (δώστε man tr) ώστε να μετατρέψει τις άνω και κάτω τελείες
που χωρίζουν τους καταλόγους του path σε αλλαγές γραμμών. Έτσι έχουμε το εξής ευανάγνωστο αποτέλεσμα:

    $ pt
    /usr/local/bin
    /usr/bin
    /usr/X11R6/bin
    /bin
    /usr/games/bin
    /opt/gnome/bin
    /opt/kde3/bin
    .

Η συνάρτηση addpath προσθέτει τα ορίσματά της στο τέλος της μεταβλητής PATH. Οι συναρτήσεις (functions) του shell είναι σαν μικρά σκριπτάκια, έχουν πιο πολλές
δυνατότητες από τα απλά aliases. Εδώ όπως βλέπετε μπορούμε να χειριστούμε μία- μία όλες της παραμέτρους της addpath().

(Για περισσότερες πληροφορίες, man bash, section FUNCTIONS)

### []{#history} [1.5 history]{#ss1.5}

Το shell μας δίνει τη δυνατότητα να επαναλάβουμε μια προηγούμενη εντολή χωρίς να χρειάζεται να την πληκτρολογήσουμε ολόκληρη.

-   Με τα βελάκια πάνω και κάτω μπορούμε να έχουμε γρήγορη πρόσβαση στις προηγούμενες εντολές.
-   Δίνοντας \'!cmd\' επαναλαμβάνεται η τελευταία εντολή που αρχιζε με τους χαρακτήρες \'cmd\'.
-   Δίνοντας \'history n\' (παρεμπιμπτόντως μην ξεχάσετε το alias h=\'history \' στο \~/.bashrc) μας εμφανίζονται οι τελευταίες n εντολές μαζί με τον αριθμό
    τους. Στη συνέχεια με \'!n\', όπου n ο αριθμός της εντολής μπορούμε να επαναλάβουμε όποια θέλουμε.
-   Με \'!-n\', όπου n αριθμός, εκτελείται η n-ιοστή προηγούμενη εντολή. Με \'!!\' εκτελείται η αμέσως προηγούμενη (συνώνυμο του \'!-1\').

(Για περισσότερες πληροφορίες, man bash, section HISTORY)

### [1.6 find]{#ss1.6}

    export FIN='-printf %s\t%TY-%Tm-%Td-%TX\t%p\n'

Έχοντας αυτή τη γραμμή στο \~/.bashrc έχω πάντα στο shell μου μια μεταβλητή, την FIN. Το κείμενο της είναι μια εντολή μορφοποίησης για τα αποτελέσματα της find.
Δίνοντας λοιπόν \"find dir \$FIN\" παίρνω μια λίστα των αρχείων κάτω από τον κατάλογο dir στην εξής μορφή:

    135987  2003-07-28-22:33:13     ./mbox

Στην πρώτη στήλη το μέγεθος του αρχείου, στη δεύτερη η ημερομηνία τροποποίησης και στην τρίτη το όνομα του αρχείου. Οι στήλες είναι χωρισμένες με tab.

Κατευθύνοντας τώρα την έξοδο της προηγούμενης εντολής στην sort μπορούμε να κάνουμε πολύ ενδιαφέροντα πράγματα:

    % find $FIN |sort -rnk 1|head -n 4

    5146003 2003-08-02-20:45:48     ./Mail/LGU
    2457441 2003-08-01-11:00:07     ./Mail/saved
    2029849 2003-02-04-20:32:24     ./tmp/lp/ss11
    1603828 2003-07-28-22:22:08     ./downl/wg/glib-2.2.2.tar.bz2

Ο διακόπτης \'-k NUM\' της sort κάνει ταξινόμηση σύμφωνα με το NUM-οστό πεδίο. Εδώ βάλαμε το πρώτο, το μέγεθος δηλαδή. Το \'r\' είναι για φθίνουσα ταξινόμηση.
Το \'n\' είναι για να λάβει η sort υπόψη της ότι πρόκειται για αριθμούς (και να μη βάλει το 11111 πριν από το 11 στη φθίνουσα ταξινόμηση, για παράδειγμα).
Χρησιμοποίησα το φίλτρο head για να κρατήσω τις πρώτες 4 γραμμές μόνο (man head).

Τι κάναμε δηλαδή; Κάναμε μια αναζήτηση κάτω από τον τρέχοντα κατάλογο και βρήκαμε τα πιο μεγάλα σε μέγεθος αρχεία.

Άλλο:

    % find $FIN |sort -rk 2|head -n 4

    20480   2003-08-03-12:32:13     ./tmp/.tips.swp
    7946    2003-08-03-12:32:13     ./tmp/tips
    4096    2003-08-03-12:32:13     ./tmp
    150606  2003-08-03-12:21:35     ./.bash_history

Κάναμε ταξινόμηση ως προς την ημερομηνία και ώρα τροποποίησης.

Παρατήρηση: Η find μας επιστρέφει και ονόματα καταλόγων (όπως το ./tmp που φαίνεται πιο πάνω). Για να μην το κάνει αυτό μπορούμε να προσθέσουμε στις παραμέτρους
της find το \'! -type d\'.

(man find για περισσότερες πληροφορίες).

### [1.7 Συντόμευση για συνηθισμένα μακριά command lines.]{#ss1.7}

Αυτό που κάναμε για την find μπορούμε να το κάνουμε και για άλλες εντολές όταν υπάρχει ένα αρκετά μακρύ command line που πληκτρολογούμε συχνά. Να μπαίνει δηλαδή
ένα κομμάτι της εντολής που είναι πάντα σταθερό σε μια μεταβλητή του shell ή αν είναι όλη η εντολή σταθερή να μπαίνει όλη σε ένα alias.

Για παράδειγμα, κάθε φορά που διαβάζω ένα ενδιαφέρον ρητό πάω και το προσθέτω σε ένα αρχείο των fortunes. Με τα παρακάτω γλυτώνω πολλή πληκτρολόγηση:

    alias addfort='pushd /usr/local/share/games/fortunes;vi quotes;strfile quotes;popd'

Για το rip ενός dvd:

    alias dvdrip='for i in `seq 1 $n` ; do mplayer -dvd $i -dumpstream -dumpfile ${i}.stream ; done'

Αφού πρώτα θέσουμε τον αριθμό τίτλων του dvd, τους κάνουμε όλους rip με μια εντολή:

    % n=3;dvdrip

Το παραπάνω μπορούσε να γίνει πιο απλά με μια συνάρτηση:

    dvdrip() { for i in `seq 1 $1` ; do mplayer -dvd $i -dumpstream -dumpfile ${i}.stream ; done ;}

οπότε θα χρειαζόταν απλά:

    % dvdrip 3

### [1.8 Διάφορα]{#ss1.8}

    alias h='history '
    alias he='head '
    alias t='tail '
    alias j='jobs -l '

Γλυτώνουμε πληκτρολόγηση\...

    alias ejclcd='eject /dev/cdrom;sleep 5s;eject -t /dev/cdrom'

Γιατί να πρέπει να κουραζόμαστε να πατάμε το κουμπί του cd όταν μπορεί να το κάνει το λινουξάκι για μας ;-) ejclcd, βγαίνει το πορτάκι, βάζουμε το δισκάκι,
κλείνει μόνο του.

    ssdu() { ls -AQ|xargs du -sb|sort -rn|cut -f 2|awk '{print "\"" $0 "\""}'|xargs du -sh ; }
    ssdus() { while test "$1";do du -sb "$1";shift;done|sort -rn|cut -f 2|awk '{print "\"" $0 "\""}'|xargs du -sh ; }

Να κάτι πιο εξεζητημένο: Η ssdu δείχνει, σε φθίνουσα σειρά, πόσο χώρο χρησιμοποιεί, σε kB/MB/GB, κάθε στοιχείο (αρχείο ή κατάλογος) του τρέχοντος καταλόγου. Και
αν θέλετε για συγκεκριμένα αρχεία/καταλόγους μονο, η ssdus παίρνει και ορίσματα.

Βασική ιδέα είναι να τρέξει πρώτα η du για να μας δώσει λίστα αρχείων και καταλόγων ταξινομημένων κατά μέγεθος. Στη συνέχεια για κάθε στοιχείο της λίστας,
παίρνουμε το όνομα και δείχνουμε μαζί και το μέγεθός του σε kB/MB/GB.


### [2. Shell prompt]{#s2}

Το command prompt του shell μπορεί να μας παρέχει σημαντικές πληροφορίες. Π.χ. βάζοντας στο \~/.bashrc τη γραμμή:

    export PS1='\u \w (\#)% '

θα πάρουμε ένα prompt του τύπου:

    manolis /usr/local/bin (15)%

που μας δείχνει το όνομα του χρήστη, τον τρέχοντα κατάλογο και τον αριθμό των εντολών που έχουμε πληκτρολογήσει. (Ο αριθμός αυτός είναι χρήσιμος για την εντολή
[history](04_tips-1.html#history)).

Το shell μας δίνει τη δυνατότητα να εμφανίσουμε στο prompt ένα σωρό χρήσιμα πράγματα, όπως το hostname (/h), τον αριθμό των εργασιών που τρέχουν στο υπόβαθρο
(/j), την ημερομηνία και ώρα (/d, /t). Φυσικά πρέπει να επιλέξει κανείς μόνο όσα πραγματικά είναι χρήσιμα γιατί ένα πολύ μακρύ prompt δυσχεραίνει τη χρήση του
τερματικού.

Μπορούμε να τρέξουμε ακόμα και ένα πρόγραμμα και να δείξουμε την έξοδό του στο prompt. Δώστε \"PS1=\'\`uptime\` % \'\" χωρίς τα εισαγωγικά. Δοκιμάστε επίσης
\"PS1=\'\\n\`fortune\`\\n \$ \'\" Κάπως περίεργο, αλλά έχει πλάκα. 8-)

Για περισσότερες πληροφορίες, man bash, section PROMPTING.


### [3. Vi (=very intelligent) editor]{#s3}

Κατ\' αρχάς διαβάστε τα tips που δίνονται στα τεύχη 22 και 27 του magaz.

Έχω βάλει στο \~/.vimrc μου τα εξής:

    map <F1> :w<CR>
    map <F2> j.
    map <F5> :bp<CR>
    map <F6> :bn<CR>
    map <F7> :files<CR>
    map <F8> :bdelete<CR>

Κάνουμε map:

-   Στο f1 το σώσιμο του αρχείου. Έτσι θα είναι πιο εύκολο να το πατάμε όλη την ώρα! Ποτέ δεν ξέρεις πότε θα χτυπήσει ο δίσκος ή θα κοπεί το ρεύμα (όποιος έχει
    καεί\...).
-   Στο f2 την εντολή \'j.\' κάνει τα εξής: Κατεβαίνει μια γραμμή (j) και επαναλαμβάνει την προηγούμενη ενέργεια αλλαγής/διόρθωσης κειμένου (.). Αυτό είναι
    χρήσιμο για να επαναλάβουμε σε πολλές γραμμές την ίδια αλλαγή με ελάχιστο κόπο.
-   Στα f5 και f6: Μεταφορά στο προηγούμενο και στο επόμενο αρχείο που είναι φορτωμένο στον vi αντίστοιχα. (Θυμίζω ότι με \':e file\' μπορούμε να ανοίξουμε ένα
    αρχείο μέσα από τον vi. Και μάλιστα, διαθέτει και autocomplete όπως το shell!)
-   Στο f7: Λίστα με όλα τα αρχεία που είναι φορτωμένα
-   Στο f8: κλείνουμε το τρέχον αρχείο.

Επίσης,

-   με την εντολή \':set tw=n\' μπορούμε να θέσουμε το μήκος του κειμένου. Το κείμενο που θα πληκτρολογούμε στο εξής θα αναδιπλώνεται αυτόματα χωρίς να
    ξεπερνάει το μήκος που ορίσαμε.
-   Με την εντολή \'gqip\' ο vi αναλαμβάνει να μορφοποιήσει την τρέχουσα παράγραφο σύμφωνα με το μήκος κειμένου που έχουμε ορίσει.

Για περισσότερα για κάθε εντολή, \'help command\' μέσα στο περιβάλλον του vi.


### [4. Screen]{#s4}

Η screen είναι ένα πολύ χρήσιμο πρόγραμμα που μας δίνει τη δυνατότητα να έχουμε σε ένα τερματικό πολλές οθόνες.

Τρέχουμε τη screen και φαίνεται να μας ανοίγει ένα νέο shell. Πατώντας \'Ctrl-A w\' (Control και A μαζί και στη συνέχεια τα αφήνουμε και πατάμε w) φαίνονται οι
οθόνες που έχουμε. Στην προκειμένη είναι μόνο μία: η νούμερο 0 με τίτλο \'bash\'. Μπορούμε να διορθώσουμε τον τίτλο πατώντας \'Ctrl-A A\'.

Πατώντας \'Ctrl-A c\' φτιάχνουμε μια καινούρια οθόνη. Άλλος τρόπος έιναι δίνοντας screen (όταν βρισκόμαστε ήδη μέσα στη screen, φτιάχνει μια καινούρια οθόνη,
δεν τρέχει νέο στιγμιότυπο της screen). Μπορούμε με \'screen -t title\' να της δώσουμε και τίτλο.

Ο πιο απλός τρόπος να τερματίσουμε μια οθόνη είναι να κάνουμε logout από το shell της.

Με \'Ctrl-A n\' μεταφερόμαστε στην οθόνη με αριθμό n. Με \'Ctrl-A Ctrl-A\' εναλλασόμαστε μεταξύ της τρέχουσας και της προηγούμενης οθόνης.

Φτιάχνοντας ένα αρχείο \~/.screenrc και προσθέτοντας την παρακάτω γραμμή

    caption always "[%n %t]%? (%W)%? (%D %d %M,%c) (%l)"

λέμε στη screen να μας δείχνει στο κάτω μέρος της οθόνης μας τις εξής πληροφορίες:

    [0 main] (1 kernel-build) (Sun 03 Aug,13:44) (1.17 1.11 1.04)

-   Τον αριθμό και τον τίτλο της τρέχουσας οθόνης σε αγκύλες.
-   Τους αριθμούς και τους τίτλους των άλλων οθονών (αν υπάρχουν) σε παρενθέσεις.
-   Την ημερομηνία και ώρα.
-   Το system load

Με τη screen μπορούμε να το παίζουμε \... σε πολλά ταμπλώ έχοντας μόνο ένα τερματικό ανοιχτό.

Επίσης, άλλη πολύ ενδιαφέρουσα δυνατότητα της screen είναι ότι μπορεί να χωρίσει την οθόνη σε πολλά οριζόντια τμήματα. Σε κάθε ένα από αυτά θα αντιστοιχεί μια
οθόνη, με δυνατότητα ρύθμισης φυσικά του ύψους του καθενός.

-   Ctrl-A S για χωρισμό της οθόνης
-   Ctrl-A X για καταστροφή τρέχοντος τμήματος
-   Ctrl-A Tab για μετάβαση στο επόμενο τμήμα
-   Ctrl-A :resize n για αλλαγή του ύψους του τρέχοντος τμήματος σε n γραμμές, (παίρνει και +n,-n για αύξηση ή μείωση κατα n αντιστοίχως).

Τέλος, με τη screen έχουμε τη δυνατότητα να κάνουμε detach και reattach ένα session.

Με (Ctrl-A d) γίνεται το detach, οπότε κλείνει η screen. Το session μας όμως δεν χάθηκε. Δίνοντας screen -ls θα πάρουμε μια έξοδο της μορφής:

    There are screens on:
            781.pts-0.linux (Attached)
            893.pts-3.linux (Attached)
            2002.pts-7.linux        (Detached)
    3 Sockets in /tmp/uscreens/S-manolis.

Με \'screen -r 2002\' (το pid δεν χρειάζεται όταν υπάρχει μόνο ένα detached session) ξανακάνουμε attach το session στο τρέχον τερματικό συνεχίζοντας τη δουλειά
μας ακριβως απο εκεί που την αφήσαμε)

Αν το session δεν είναι detached και δεν έχουμε, για κάποιο λόγο, πρόσβαση σ\' αυτό μπορούμε να χρησιμοποιήσουμε την εντολή \'screen -d -r pid\' η οποία κάνει
πρώτα detach κι ύστερα attach στο τρέχον τερματικό.

Μια περίπτωση στην οποία αυτή η ιδιότητα είναι πολύ χρήσιμη είναι σε remote shells. Ας υποθέσουμε ότι συνδέόμαι με telnet σε ένα απομακρυσμένο unix box και
αρχίζω να κάνω μια δουλειά. Μπορώ ανά πάσα στιγμή να κάνώ detach και να τερματίσώ τη σύνδεση. Όταν αργότερα ξανασυνδεθώ, κάνω attach το προηγούμενο session και
συνεχίζω τη δουλειά μου από εκεί που την άφησα!

