Προς το περιεχόμενο

Προγραμμα φλοιου Bash, ευκολουλι για σας!


christian-ago

Προτεινόμενες αναρτήσεις

Υπαρχει μια εντολη στο linux(bt4), η οποία παίρνει ως 1ο όρισμα ένα αρχειο και ως 2ο πάλι ενα αρχειο. Για ευνοητους λογους δεν μπορω να τη δημοσιευσω εδω γι αυτο και δινω τον κωδικα ως εχει χωρις την εντολη.

Υπαρχει καποιος τροπος να δινω στην εντολη ως ορισματα φακελους και να διατρεχει ολα τα αρχεια αυτου του φακελου; Αυτη ειναι και η ουσια του προγραμματος. Να διευκολυνει τους χρηστες και να δινουν ένα φακελο και η "πονηρη" εντολη να διατρεχει ολα τα αρχεια του φακελου αυτου χωρις να δινει χειροκινητα ο χρηστης αρχεια σε καθε εκτελεση της εντολης, κατι που προφανως ειναι κουραστικο. Εν τω μεταξυ το προγραμμα θα εμφανιζει ενα ποσοστο ολοκληρωσης της εντολης στην οθονη του χρηστη.

Οταν βρει αυτο που εχει να βρει το προγραμμα εμφανιζει στο χρηστη το "κλειδι" και σε ποια γραμμη βρισκεται. Πως μπορω να αλλαξω το προγραμμα μου για να δουλεψει οπως ειπα παραπανω;

 

>#!/bin/bash

count=0
num=0
per=0

echo -n "Dwse diadromi gia arxeia: "
read cap

echo -n "Dwse diadromi gia lexika: "
read dict

for file in $cap
do
let num=num+1
done

for file in $dict
do

"poniri_entoli"-ng -z $cap -w $dict >> out.txt

let count=count+1
let per=count*100/num
echo $per%
done

clear

if ( grep -n FOUND out.txt ) then
echo "KEY(S) FOUND!!!!!!!!!"
else
echo "Tzifos :("
fi

echo -n "You want me to open output file? "
read answer
if [ "$answer" == "n" ]; then
exit 0
elif [ "$answer" == "y" ]; then
kate out.txt
fi

exit 0

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Μάλλον ψάχνεις κάτι σε nested loops άν κατάλαβα καλά αυτό που ζητάς

>for i in `ls /path/to/files`; do
   for j in `ls /path/to/dicts`; do
       command-ng -z $i -w $j >> out.txt
   done
done

 

Γιά το progress bar αργότερα αν βρώ λίγο χρόνο.

 

Για να έχεις και progress bar δοκίμασε το παρακάτω

>WIDTH=$(( $(tput cols) - 11 ))
TOTAL=(( $(ls -l /path/to/cap | wc -l) * $(ls -l /path/to/dic | wc -l) ))
CURRENT=0

for i in `ls /path/to/files`; do
   for j in `ls /path/to/dicts`; do
       command-ng -z $i -w $j >> out.txt
	(( CURRENT++ ))
	pct=$((( $WIDTH * $CURRENT ) / $TOTAL ))

	echo -en "\r[ "
	for h in $(seq 1 $pct); do
		echo -ne "="
	done
	echo -ne ">"
	for p in $(seq $pct $(( $WIDTH - 1))); do
		echo -ne "-"
	done
	echo -ne " ] "
	echo -ne $((( 100 * $pct ) / $WIDTH ))
	echo -ne "%"
	sleep 1
   done
done

 

Δέν σου υπόσχομαι οτι θα δουλέψει 100% δέν το δοκίμασα καθόλου, από μνήμης το έγραψα. Άμα σου βγάλει error εδώ είμαστε. Για να σου ανοίγει το αρχέιο του output κτλ φαντάζομαι οτι μπορείς να το καταφέρεις και μόνος σου.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Επειδη δε γνωριζω καλα φλοιο, τον κωδικα που μου εδωσες για τα nested loops πού ακριβως θα τον ενσωματωσω στον κωδικα μου;

Επισης μπορεις να μου εξηγησεις τι σημαινει το:

/path/to/files και το /path/to/dicts?

Ευχαριστω και παλι!

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Πρώτα-πρώτα, τα /path/to/files είναι το directory που έχεις κάνει το capture του network traffic (εντελώς τυχαίο παράδειγμα) και το /path/to/dicts είναι το path στο directory που έχεις αποθηκευμένα τα dictionaries (και πάλι τυχαίο παράδειγμα). Εν ολίγοις, το /path/to/files είναι το path που έχει μέσα τα αρχεία που θα δώσεις σαν parameter στο τέλος της κρυφής εντολής σου, ενώ το /path/to/dicts είναι το path στο directory που έχει μέσα τα αρχεία που δίνεις σαν παράμετρο στο -w.

Τώρα όσον αφορά τα nested loops, (δέν είναι όρος συγκεκριμένος για το bash ή για οποιοδήποτε άλλο shell αλλά γενικότερος όρος στο development) θα μπορούσαν να είναι και από μόνα τους όλο το script που θέλεις απλώς δέν εμφανίζουν αποτελέσματα του στύλ "βρήκα key". Παίρνεις στο τέλος του execution του script το out.txt και το κοιτάς μόνος σου.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δηλαδη να αλλαξω τον κωδικα και να εχω κατι σαν αυτο;

Δε μου φαινεται σωστο.

Οπως ειπα δε γνωριζω bash φλοιο και προσπαθω να μαθω λιγο παραδοξα...

>#!/bin/bash

count=0
num=0
per=0
echo -n "Dwse diadromi gia arxeia: "
read cap

echo -n "Dwse diadromi gia lexika: "
read dict

for file in $dict;
do
let num=num+1
done

for i in `ls /path/to/files`; do
   for j in `ls /path/to/dicts`; do
command-ng -z $i -w $j >> out.txt

let count=count+1
let per=count*100/num
echo $per%
done
done

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Επειδή μάλλον με το να σου εξηγήσω θα σε μπερδέψω περισσότερο, προτείνω να ξεκινήσεις με το να πάρεις το 1ο script και να το τρέξεις ώς έχει αλλάζοντας φυσικά αυτά που λέγαμε, τα /path/to/dicts με το παγματικό path στο οποίο βρίσκονται τα λεξικά σου και το /path/to/files με το πραγματικό path στο οποίο βρίσκονται τα captures σου. Και μετά θα το συζητήσουμε διαξοδικότερα το θέμα του ποσοστού που θέλεις να εμφανίζεται. :-)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Εγινε θα το κανω. Αλλα νομιζω οτι ο χρηστης θελω να δινει αυτες τις 2 διαδρομες και οχι να τις οριζω εγω στο προγραμα.

Δηλαδη οταν ζητειται απο το χρηστη να πληκτρολογησει φακελο,

να αποθηκευεται στη μεταβλητη cap και οι βροχοι μετα να διατρεχουν το φακελο αυτο.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Εντάξει αυτό δεν είναι το κύριο θέμα. Γίνεται είται έτσι όπως το έχεις κάνει εσύ και αντί για το πραγματικό path εκεί που λέει /path/to κλτ κτλ να βάζεις το όνομα της μεταβλητής στην οποία αποθηκεύεις τηνεπιλογή του χρήστη (π.χ. $cap και $dict στον δικό σου κώδικα) είτε τα παίρνεις σαν παραμέτρους στο script με τις ειδικές μεταβλητές $1 και $2.

Και ειδικά για το bash, το man page του είναι τρομερά κατατοπιστικό, ρίξε μιά ματιά και σε αυτό αφού διαβάσεις λίγο τον κώδικα και θα σου λυθούν πολλές απορίες.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αυτο που καταλαβαινω εγω ειναι το εξης:

 

>#!/bin/bash

count=0
num=0
per=0
echo -n "Dwse diadromi gia arxeia: "
read cap

echo -n "Dwse diadromi gia lexika: "
read dict

for file in $dict;
do
let num=num+1
done

[b]for i in `ls $1`[/b]; do
   [b]for j in `ls $2[/b]`; do
command-ng -z $i -w $j >> out.txt

let count=count+1
let per=count*100/num
echo $per%
done
done

 

Φυσικα δεν ειναι σωστο. Τι κανω λαθος;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

ΟΚ ας το πάρουμε με τη σειρά. Κατ' αρχάς ο "σωστός" κώδικας είναι αυτός

>#!/bin/bash
count=0
num=0
per=0
echo -n "Dwse diadromi gia arxeia: "
read cap

echo -n "Dwse diadromi gia lexika: "
read dict

for file in $dict; do
   (( num++ ))
done

for i in `ls $cap`; do
   for j in `ls $dict`; do
command-ng -z $i -w $j >> out.txt
       (( count++ ))
       echo $((( 100 * $count ) / $num ))
   done
done

 

Αυτό που είχες γράψει εσύ είχε ένα λάθος.

>for i in `ls [b]$1[/b]`; do
   for j in `ls [b]$2[/b]`; do
command-ng -z $i -w $j >> out.txt

Όπως σου είπα πρίν, οι μεταβλητές $1, $2, $3... είναι special variables οι οποίες παίρνουν τιμές από την εντολή με την οποία τρέχεις το script. Για να γίνει λίγο πιό κατανοητό τρέξε το παρακάτω script

>#!/bin/bash
echo "My name is: $0

και παρατήρησε το output. Θα δείς οτι η μεταβλητή $0 κρατάει πάντα το 1ο μέρος του command line που είναι πάντα το όνομα του script.

Όμοια, οι μεταβλητές $1, $2 κτλ κρατάνε τα επόμενα κομμάτια (space separated) τα οποία μπορούνε να είναι παράμετροι για αυτό το script. Άν στο δικό σου δηλαδη ήθελες να περνάς τα directories που έχουν τα αρχεία που χρειάζεσαι μέσα χωρίς να ρωτάς τον χρήστη αλλά κάπως έτσι:

>./myscript.sh /home/foo /home/bar

υποθέτοντας οτι το /home/foo έχει το traffic capture και το /home/bar έχει τα dictionaries, τότε μέσα στον κώδικα του script σου και χωρίς να ρωτήσεις τον χρήστη τίποτα, θα τις έπαιρνες αυτές τις τιμές με το $1 για την 1η και με το $2 για την 2η ακριβώς όπως στο δικό σου τελευταίο παράδειγμα.

Επίσης, για να μετρήσεις πόσες παραμέτρους σου έχει περάσει ο χρήστης στο command line του script υπάρχει η μεταβλητή $# που σου επιστρέφει τον αριθμό των παραμέτρων χωρίς να προσμετρά το 1ο, δηλαδή το όνομα του script. Παράδειγμα για να γίνω λίγο πιό κατανοητός:

>#!/bin/bash
echo "You have given me $# parameters"

Δοκίμασε να το τρέξεις αυτό το script με πολλούς τρόπους για να δείς τί σου επιστρέφει. Π.χ. ./myscript.sh σκετο αλλά και ./myscript.sh par1 par2 par3

Αυτά τα ολίγα αλλά επαναλαμβάνω οτί πρέπει να ρίξεις οπωσδήποτε μιά ματιά αν μή τι άλλο στο man bash. :-)

Επίσης να πώ οτι όλα τα παραπάνω ισχύουν για το bash αλλά οχι αναγκαστικά και για άλλα shells.

 

EDIT: Θα πρόσεξες οτι υπάρχουν και άλλες αλλαγές στο script σου αλλά οι περισσότερες είναι θέμα προτίμησης όπως π.χ. το (( variable++ )) που μου κάθεται καλύτερα από το var=var+1 καθώς και η αλλαγή στον υπολογισμό του ποσοστού η οποία αφενός είχε syntax error γιατί το keyword let που χρησιμοποιούσες θέλει την πράξη που ακολουθεί κλεισμένη σε "", αφ' ετέρου, δέν είμαι καθόλου σίγουρος οτι θα μπορσε να κάνει και τον πολλαπλασιασμό και τη διαίρεση σε ένα expression. Φυσικά μπορεί να κάνω και λάθος :P.

Επίσης, πρόσεξε το εξής που δεν το δοίρθωσα επείτηδες. Όταν μετράς το σύνολο των αρχείων που υπάρχουν στο ένα directory για να ξέρεις στο πόσο count θα έχεις φτάσει στο 100%, δέν έχεις λάβει υπ' όψη σου τον αριθμό των αρχείων που μπορεί να υπάρχουν και στο 2ο path με τα οποία τα πρώτα θα συνδιαστούνε ανά 2. Δηλαδή, το σημείο αναφοράς σου πρέπει να είναι το γινόμενο του αριθμού των αρχείων του 1ου directory με τον αριθμό των αρχείων του 2ου.

Τέλος, βελτιωσεις μπορούνε να γίνουνε γιατί δέν χρειάζεται π.χ. να κάνεις loop για να μετρήσεις τα αρχεία του directory, ένα απλό ls -l σε συνδιασμό με pipe στην wc θα σου έδινε τνο αριθμό που ζητάς. Αλλά άν έχεις κέφι και θέλεις να ασχοληθείς προσπάθησέ για εξάσκηση.

Αυτά και τέλος :P

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αυτο με τις special variables το καταλαβα. Ειναι για να δωσεις παραμετρους κατα την εκτελεση του προγραμματος αν το λεω σωστα. Πχ.

 

>./myscript.sh par1 par2

 

Οσο για το count των αρχειων θα ηθελα να μετρησω μονο το φακελο που βρισκονται τα λεξικα αλλα αυτο ειναι λεπτομερεια.

 

Πηρα αυτουσιο τον κωδικα που μου εδωσες και δεν κανει αυτο που πρεπει να κανει η εντολη.

Για δωσε μου ενα παραδειγμα που τρεχεις το προγραμμα.

Πχ. εγω το τρεχω ως εξης:

 

>#./myscript
#caps #ειναι ο φακελος που βρισκονται τα captures-βρίσκεται στο root [ENTER]
#dicts #ειναι ο φακελος που βρισκονται τα λεξικα-βρίσκεται στο root. [ENTER]

 

Τα captures οπως βλεπω απο το output (out.txt) βλεπω οτι τα ανοιγει,

αλλα δεν ανοιγει τα λεξικα, δεν συνδυαζει δηλαδη τους δυο φακελους μεταξυ τους

γιατι μαλλον δε βρισκει καποιο λεξικο στο φακελο dicts για να ανοιξει.

 

Επισης οταν με την echo εμφανιζεις το ποσοστο στην οθονη, αυτο δεν αποθηκευεται

λογικα σε καποια μεταβλητη ετσι ειναι στον αερα.

Πως θα μπορουσα να αποθηκευσω το result σε μια μεταβλητη για μελλοντικη χρηση;

Οπως ειπες η let δεν κανει πολ/μο και διαρεση ταυτοχρονα.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Πρέπει να σιγουρευτείς οτι δίνεις το σωστό path για να βρεί τα αρχεία που θέλεις. Δοκίμασε να δώσεις το absolute path εκεί που ρωτάς τον χρήστη π.χ. /home/username/dictionaries.

Κάνε το ίδιο και για το path των captures. Άν δέν το κάνεις αυτό, το bash θα νομίζει οτι μιλάς για directories που βρίσκονται κάτω από το path από το οποίο εκτελέιται το script.

Άν δέν φταίει αυτό, κάνε ένα echo τις μεταβλητές $i και $j που θα πρέπει να περιέχουν το path μαζί με το filename και κοίτα τί πάει στραβά.

Για να αποθηκεύσεις το ποσοστό σε μεταβλητή απλώς κάνεις store την πράξη σε μιά μεταβλητή και κάνεις echo την μεταβλητή π.χ.

>percentage=$((( 100 * $count ) / $num ))
echo $percentage%

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...