[BASH] Hulp gevraagd. Script dat file extensie zoekt, opties

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • bn326160
  • Registratie: Juni 2009
  • Laatst online: 29-09 21:24
Hallo, ik was wat aan het prutsen met bash afgelopen maand en tracht nu een script te schrijven.
De bedoeling is dat het script doorheen mappen kan zoeken naar bestanden met een bepaalde extensie. De extensie wordt aangegeven met argument -e, de mappen worden gedefinieerd door de argumenten zonder '-optie'. De uitvoer is in 2 kolommen waarbij de gevonden bestanden in kolom 1 staan en de respectievelijke map in kolom 2.

Is het mogelijk mijn script even door te nemen en me te vertellen of dit wel de meest efficiënte of flexibele manier is die ik gekozen heb? Flexibel omdat er opties moeten worden toegepast.

Verder lukt het me ook niet om het '-l commando' werkende te krijgen. Enig idee wat er mee scheelt? De extensie invoeren door een variabele in de '-name tag' van 'find' te gebruiken lukt wel, maar voor de eerste letter van een woord dan weer niet? Alsook hoe kan je het script laten herkennen dat er een range gebruikt wordt? Met een if-functie die zoekt naar een '-'?

Ik denk dat het me wel gelukt is een block device te mounten op die manier, maar hoe kan ik het pad daarvan dan instellen als een extra parameter? Het pad toewijzen aan een nummer variabele lijkt niet te lukken.

Dan lukt het bijvoorbeeld wel perfect om de 'no recursion' tag te gebruiken, maar 'no numbers' dan weer niet. Hoe is dit verschillend van elkaar?

Voor de 'no recusion' (nn) en 'no numbers' (nr) tags gebruik ik een lange tag en dien dus ook '--' voor de opties in te voeren. Is het mogelijk om slechts 1 liggend streepje te gebruiken? Dit is normaal gezien niet mogelijk met getopt. Met getopts dan weer wel, maar daarbij slaag ik er niet in om de argumenten zonder '-tag' nog te gebruiken. Iemand enig idee hoe dit oplosbaar is?

En tenslotte, is het mogelijk dat wanneer ik 2 bestanden met dezelfde naam vind, hij dit slechts 1 maal weergeeft, maar wel witregels houdt zodat er rechts nog de respectievelijke map bij staat.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/bin/bash

#FUNCTIONS
#Foutmelding
#Wordt ook naar error file geschreven
fout() {
  echo 1>&2;
  echo "Fout, onvoldoende argumenten" 1>&2;
  echo "Gebruik: $0 [-e <extensie>] [<folder>]" 1>&2;
  echo "Gelieve de extensie op te geven met argument -e en minstens 1 map waarin gezocht moet worden naar die extensie." 1>&2;
  echo "Voor meer info gelieve Help te raadplegen met argumenten -h of --help." 1>&2;
  echo 1>&2;
  exit
 }

#Help
help() {
  echo
  echo "--- Help ---"
  echo
  echo "Dit script gaat op zoek naar bestanden met een bepaalde extensie, in één of meerdere directories. De output geeft weer welke bestanden gevonden werden, gevolgd door de directory waar het respectievelijke bestand zich bevindt."
  echo
  echo "De het argument -e <ext> is vereist, anders kan er geen extensie gevonden worden."
  echo "Andere argumenten zijn de te doorzoeken directories."
  echo
  echo "Verder bevat dit script de volgende optionele argumenten:"
  echo "-h of --help geeft dit help-document weer."
  echo "-l <letter> zoekt enkel bestanden, die beginnen met de letter <letter>."
  echo "-l <letter1>-<letter2> doet hetzelfde, maar zoekt alles van <letter1> t.e.m <letter2>."
  echo "-b <block-device> laat toe een partitie te doorzoeken, door ze (automatisch) te mounten in de directory /mnt en dan nadien deze directory te gaan doorzoeken."
  echo "--nn (no numbers) belet dat in een bestandsnaam een cijfer 0 tot 9 voorkomt."
  echo "--nr (no recursion) voorkomt dat je programma ook in onderliggende directories gaat zoeken."
  echo "-f of &#8211;-fout <bestand> schrijft mogelijke fouten die optreden (bvb een niet-leesbare directory) weg naar het bestand <bestand>."
  echo "-s <woord> zoekt binnen de gevonden bestanden het woord <woord>, en geeft enkel die bestanden weer die ook dit woord bevatten."
  echo
  exit
}

#VARS

#getopt uitvoeren
OPTS=$(getopt -o e:hl:b:f:s: -l "help,nn,nr,fout" -n "ExamenScript" -- "$@");

#Slechte opties
if [ $? -ne 0 ];
then
  fout;
  exit
fi

#Opties verplaatsen
eval set -- "$OPTS";

#echo "AFTER SET -- \$OPTS: $@";

while true; do
  case "$1" in
    -e)
      shift;
      if [ -n "$1" ]; then
        EXT=$1;
        shift;
      fi
      ;;
    -h|--help)
      shift;
      help;
      ;;
    -l)
      shift;
      if [ -n "$1" ]; then
        CHAR=$1;
        shift;
      fi
      ;;
    -b)
      shift;
      if [ -n "$1" ]; then
        sudo mkdir /mnt/$1;
        sudo echo -e "/dev/$1       /mnt/$1           vfat    defaults        0       0 " >> /etc/fstab;
        sudo mount -a;
        999=/mnt/$1;
        shift;
      fi
      ;;
    --nn)
      shift;
      NONUM=" ! -name '*[0-9]*'";
      ;;
    --nr)
      shift;
      NOREC="-maxdepth 1";
      ;;
    -f|--fout)
      shift;
      if [ -n "$1" ]; then
        ERROR="| 2>filename | tee -a $1";
        shift;
      fi
      ;;
    -s)
      shift;
      if [ -n "$1" ]; then
        echo "-e used: $1";
        shift;
      fi
      ;;
    --)
      shift;
      break;
      ;;
  esac
done

#Geen map/opties opgegeven
if [ $# -lt 1 ];
then
  fout;
  exit
fi

echo "Resterende argumenten: $@" >2;

echo \# $# >2;

#Arrays aanmaken met de bestandsnaam en map
FILES=( $(find $@ $NOREC $NONUM -name \*.${EXT} $ERROR | rev | cut -d/ -f 1 | rev) )
FOLDERS=( $(find $@ $NOREC $NONUM -name \*.${EXT} $ERROR | rev | cut -d/ -f 1 --complement | rev) )
#Arrays in 2 kolommen weergeven
for ((i = 0; i <= ${#FILES[@]}; i++));
do
    printf '%s %s\n' "${FILES[i]}" "${FOLDERS[i]}"
done | column -t | sort -k1 #Kolommen duidelijker maken + Sorteren op bestandsnaam


Alvast bedankt voor de hulp en tips die me op de goede weg zouden kunnen helpen!

🤞🏻


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 21:30

Hero of Time

Moderator LNX

There is only one Legend

En dit lijkt tevens wel erg op een schoolopdracht. Getuige ook de term "ExamenScript" in je code. Hulp vragen mag, maar we gaan geen complete antwoorden geven, laat staan je opdracht maken.

Als je niet weet hoe je verder moet gaan, moet je voor jezelf eens op een rijtje zetten wat het moet doen. Stap voor stap, niet tegelijk. Daarna ga je kijken welke commando's je voor welke functie nodig hebt. Je lijkt het complexer te maken dan nodig is.

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

Verwijderd

Ik vind het script een verschrikking. Files in een directory zoeken doe je inderdaad met bijvoorbeeld
find /usr/lib /usr/share/lib '(' -name '*.so'  -o -name '*.la' ')' -printf '%f\t%h\n'


Wat je verder allemaal doet en wilt doen is me een raadsel. Waarom moet dat script een block device mounten? En dan de tweede vraag, waarom schrijft het script in godsnaam naar /etc/fstab? Ik zou dit scirpt op door mij beheerde systemen direct van het systeem verwijderen en de root-privileges intrekken van degene die dit soort dingen schrijft. Je doet ook nog eens geen controle op het -b argument waardoor het systeem gemakkelijk gesloopt kan worden.

Waarom doe je iets met beginletters en extensies? Het klinkt nogal random, je beperkt alleen maar de mogelijkheden van find, bijvoorbeeld:
find /usr/lib /usr/share/lib '(' -name 'a*' -a '(' -name '*.so'  -o -name '*.la' ')' ')' -printf '%f\t%h\n'

Of
find /usr/lib -regex '.*/a[^/]*\(so\|la\)' -printf '%f\t%h\n'


Verder, no numbers? Wat is het nut daarvan? Weer een of andere random optie. Dat no recursion snap ik nog wel.

En dan als laatst, wat is het doel van het formaat file + directory in de output? Wat moet het script verder gaan doen, want aan alleen een wrapper voor find heb je zo weinig. Alles is te doen met opties, waarbij regular expressions het dichtst in de buurt komen van wat je wilt bereiken. Het automatisch mounten zou ik absoluut laten vallen. Dat horen scripts niet zomaar te doen.

Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 23:01
Wat @Cheatah al heeft gezegd, met daarbij nog wat andere (rare / overbodige) dingen en details:
code:
1
2
if [ $? -ne 0 ];
then

Die ; hoef je hier alleen neer te zetten als de then op dezelfde regel staat als de haakjes. Een commando wordt ofwel gescheiden door een ; ofwel door een nieuwe regel.

De exit van #48 en #119 zijn overbodig.

sudo oproepen in je script is raar. Dan krijg je opeens een wachtwoord vraag. Zorg gewoon dat je script root rechten eist, maar de vraag is inderdaad waarom je mount in je script.

#127:
code:
1
2
echo "/home/ssh/test.txt" | xargs basename
test.txt


#128
code:
1
2
echo "/home/ssh/test.txt" | xargs dirname
/home/ssh


#133
In plaats van een colum -t kan je ook gewoon dit doen:
code:
1
2
3
4
printf "%-15s\t%-15s\n" "aap" "nootmies";
printf "%-15s\t%-15s\n" "aapnoot" "mies";
aap             nootmies
aapnoot         mies

anders had je net zo goed op #132 een echo kunnen doen i.p.v. een printf

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • bn326160
  • Registratie: Juni 2009
  • Laatst online: 29-09 21:24
Bedankt allemaal! Ik heb het script vandaag herschreven, met een aantal loops haal ik argumenten voor find aan, uiteindelijk worden die allemaal in find geplaatst.

Alleen krijg ik helemaal geen output :s

Wanneer ik de echo van m'n variabele achter een find kopieer werkt het namelijk wel. Iemand die hulp kan bieden?

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/bin/bash

#FUNCTIONS
#Foutmelding
charfout(){
  echo "Uw ingevoerde eerste letter met argument -l is ongeldig."
  echo "Gebruik: $0 -e <extensie> -l <a>/<a-c>"
}

extfout() {
  echo 1>&2;
  echo "Fout, onvoldoende argumenten" 1>&2;
  echo "Gebruik: $0 [-e <extensie>] [<folder>]" 1>&2;
  echo "Gelieve de extensie op te geven met argument -e en minstens 1 map waarin gezocht moet worden naar die extensie." 1>&2;
  echo "Voor meer info gelieve Help te raadplegen met argumenten -h of --help." 1>&2;
  echo 1>&2;
  exit
 }

#Help
help() {
  echo
  echo "--- Help ---"
  echo
  echo "Dit script gaat op zoek naar bestanden met een bepaalde extensie, in één of meerdere directories. De output geeft weer welke bestanden gevonden werden, gevolgd door de directory waar het respectievelijke bestand zich bevindt."
  echo
  echo "De het argument -e <ext> is vereist, anders kan er geen extensie gevonden worden."
  echo "Andere argumenten zijn de te doorzoeken directories."
  echo
  echo "Verder bevat dit script de volgende optionele argumenten:"
  echo "-h of --help geeft dit help-document weer."
  echo "-l <letter> zoekt enkel bestanden, die beginnen met de letter <letter>."
  echo "-l <letter1>-<letter2> doet hetzelfde, maar zoekt alles van <letter1> t.e.m <letter2>."
  echo "-b <block-device> laat toe een partitie te doorzoeken, door ze (automatisch) te mounten in de directory /mnt en dan nadien deze directory te gaan doorzoeken."
  echo "--nn (no numbers) belet dat in een bestandsnaam een cijfer 0 tot 9 voorkomt."
  echo "--nr (no recursion) voorkomt dat je programma ook in onderliggende directories gaat zoeken."
  echo "-f of &#8211;-fout <bestand> schrijft mogelijke fouten die optreden (bvb een niet-leesbare directory) weg naar het bestand <bestand>."
  echo "-s <woord> zoekt binnen de gevonden bestanden het woord <woord>, en geeft enkel die bestanden weer die ook dit woord bevatten."
  echo
  exit
}


#Opties in getopt instellen + argumenten in volgorde plaatsen (mappen achter case-opties)
OPTS=$(getopt -o e:hl:b:f:s: -l "help,nn,nr,fout" -n "ExamenScript" -- "$@");
eval set -- "$OPTS";

#Case doorlopen om opties aan respectievelijke variabelen toe te wijzen
while true; do
  case "$1" in
    -e)
      shift;
      if [ -n "$1" ]; then
        BESTANDSEXTENSIE=$1;
        shift;
      fi
      ;;
    -h|--help)
      shift;
      help;
      ;;
    -l)
      shift;
      if [ -n "$1" ]; then
        BEGINLETTER=$1;
        shift;
      fi
      ;;
    -b)
      shift;
      if [ -n "$1" ]; then
        BLOCKDEVICE=$1;
        shift;
      fi
      ;;
    --nn)
      shift;
      NONUMBERS=true;
      ;;
    --nr)
      shift;
      NORECURSION=true;
      ;;
    -f|--fout)
      shift;
      if [ -n "$1" ]; then
        FOUTLOG=true;
        shift;
      fi
      ;;
    -s)
      shift;
      if [ -n "$1" ]; then
        ZOEKEN=$1;
        shift;
      fi
      ;;
    --)
      shift;
      break;
      ;;
  esac
done

#De overige argumenten, ergo de te-doorzoeken-folders, in een array plaatsen
TEDOORZOEKENFOLDERS=("$@")

#De array van folders als eerste argumenten van de find functie opgeven
FINDARGUMENTEN=$(printf "%s " "${TEDOORZOEKENFOLDERS[@]}")

#Nagaan of er een block device gemount dient te worden
if [[ $BLOCKDEVICE ]]; then
  echo "Gelieve admin rechten te geven om het block-device te kunnen mounten."
  sudo mount /dev/$BLOCKDEVICE /mnt
  FINDARGUMENTEN=$FINDARGUMENTEN" /mnt" #Pad van gemounte drive aan array toevoegen
fi

#Indien de no-recursion vlag gebruikt is, enkel level 1 mappen toestaan
if [[ $NORECURSION ]]; then
  FINDARGUMENTEN=$FINDARGUMENTEN" -maxdepth 1"
fi

#Beargumenteren dat er naar bestanden moet gezocht worden (type -f)
FINDARGUMENTEN=$FINDARGUMENTEN" -type f"

#De extensie implementeren door een naamfilter aan find toe te voegen
#Indien geen extensie opgegeven, foutmelding
if [[ $BESTANDSEXTENSIE ]]; then
  FINDARGUMENTEN=$FINDARGUMENTEN" -name \*.${BESTANDSEXTENSIE}"
else
  extfout
fi

#Nagaan hoeveel karakters er aan het -l argument toegewezen zijn
case ${#BEGINLETTER} in
  0) #Niet toewijzen
    ;;
  1) FINDARGUMENTEN=$FINDARGUMENTEN" -name '${BEGINLETTER}*'" #Beginnen met een letter
    ;;
  3) FINDARGUMENTEN=$FINDARGUMENTEN" -name '[${BEGINLETTER}]*'" #Beginnenn met een letter-range
    ;;
  *) charfout
    ;;
  esac

#Indien de no-numbers vlag gebruikt is, nummers verbieden in de bestandsnaam
if [[ $NONUMBERS ]]; then
  FINDARGUMENTEN=$FINDARGUMENTEN" \! -name '*[0-9]*'"
fi


echo $FINDARGUMENTEN

find $FINDARGUMENTEN



#FILES=( $(find ${ARG} | rev | cut -d/ -f 1 | rev) )
#FOLDER=( $(find ${ARG} | rev | cut -d/ -f 1 --complement | rev) )
#Arrays in 2 kolommen weergeven
#for ((i = 0; i <= ${#FILES[@]}; i++));
#do
#    printf '%s %s\n' "${FILES[i]}" "${FOLDER[i]}"
#done | column -t | sort -k1 #Kolommen duidelijker maken + Sorteren op bestandsnaam


Op regel 152 roep ik de variabele nogmaals op, maar regel 154 voert niet uit.
Wanneer ik de output van de echo op r152 kopieer en achter een find plak werkt het perfect.
Hoe los ik dit op?
[b][message=42362069,noline]
#127:
code:
1
2
echo "/home/ssh/test.txt" | xargs basename
test.txt


#128
code:
1
2
echo "/home/ssh/test.txt" | xargs dirname
/home/ssh


#133
In plaats van een colum -t kan je ook gewoon dit doen:
code:
1
2
3
4
printf "%-15s\t%-15s\n" "aap" "nootmies";
printf "%-15s\t%-15s\n" "aapnoot" "mies";
aap             nootmies
aapnoot         mies

anders had je net zo goed op #132 een echo kunnen doen i.p.v. een printf
Bedankt! Zal ik nog aanpassen!

🤞🏻


Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 21:30

Hero of Time

Moderator LNX

There is only one Legend

Waarom stuur je eigenlijk alle echo's van functie fout() naar stderr? Het is ook makkelijker te doen overigens, door dit idee toe te passen:
code:
1
2
3
4
5
6
7
fout() {
  (
    echo "dit is fout"
    echo "doet het opnieuw"
    echo "zie --help voor meer info"
  ) >&2
}

Scheelt je overal 1>&2 achter te typen.

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 23:01
Of:
code:
1
2
3
4
5
fout() {
        echo "dit is fout
doet het opnieuw
zie --help voor meer info" 1>&2
}


Of
code:
1
2
3
fout() {
        echo -e "dit is fout\ndoet het opnieuw\nzie --help voor meer info" 1>&2
}

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • bn326160
  • Registratie: Juni 2009
  • Laatst online: 29-09 21:24
Hero of Time schreef op dinsdag 10 juni 2014 @ 20:50:
Waarom stuur je eigenlijk alle echo's van functie fout() naar stderr? Het is ook makkelijker te doen overigens, door dit idee toe te passen:
code:
1
2
3
4
5
6
7
fout() {
  (
    echo "dit is fout"
    echo "doet het opnieuw"
    echo "zie --help voor meer info"
  ) >&2
}

Scheelt je overal 1>&2 achter te typen.
Omdat er ook nog een functie moet komen die de stderr logt naar een bestand. Wel handig dat de foutmeldingen dan ook gelogd worden leek me.

🤞🏻


Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 23:01
Aangezien je het maar op één plek doet kan je toch gewoon dit doen:
code:
1
echo "bla bla bla" >> /var/log/examenscript

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 21:30

Hero of Time

Moderator LNX

There is only one Legend

bn326160 schreef op dinsdag 10 juni 2014 @ 21:29:
[...]

Omdat er ook nog een functie moet komen die de stderr logt naar een bestand. Wel handig dat de foutmeldingen dan ook gelogd worden leek me.
Heb je wel getest wat ik heb geschreven? Dat is precies wat ik doe, maar ipv het tien keer te schrijven, dump ik alle uitvoer wat er gegenereerd wordt in een keer erheen.

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

  • bn326160
  • Registratie: Juni 2009
  • Laatst online: 29-09 21:24
Hero of Time schreef op dinsdag 10 juni 2014 @ 23:39:
[...]

Heb je wel getest wat ik heb geschreven? Dat is precies wat ik doe, maar ipv het tien keer te schrijven, dump ik alle uitvoer wat er gegenereerd wordt in een keer erheen.
Jazeker, dat was gewoon een antwoord op je vraag! Bedankt, ik heb het toegepast ;)

🤞🏻

Pagina: 1