Re: Lidt korn shell scripting [array]

From: per engelbrecht (none@per--xterm.dk.lh.bsd-dk.dk)
Date: Fri 07 Oct 2005 - 00:27:17 CEST


Date: Fri, 07 Oct 2005 00:27:17 +0200
From: per engelbrecht <none@per--xterm.dk.lh.bsd-dk.dk>
To: "Lasse H.Petersen" <none@lhp--toft-hp.dk.lh.bsd-dk.dk>, bsd-dk@bsd-dk.dk
Subject: Re: Lidt korn shell scripting [array]

Lasse H.Petersen wrote:
> Per skrev:
>
> (Dennis skrev:)
>
>>> find . -type f -name "*.$tld[*]" -print | while
>
>
> Det vil ikke kunne virke.
>
>> #! /bin/ksh
>> #
>> # Update snumber recursive in all zone files, copy zonefiles and
>> append #.internal to all new files.
>> # PE
>> #
>>
>> v1='com'
>> v2='net'
>> v3='dk'
>> v4='de'
>> v5='se'
>> v6='nl'
>> v7='ru'
>>
>> find . -type f -name "*.$v*" -print | while read i
>
>
> Det virker heller ikke, af samme årsag, men kunne evt se ud som om det
> gjorde!

Hej Lasse

Det virker helt perfekt!
Ville bare gerne vide hvorfor brugen af array ikke gjorde.

>
> able:~ $ cat test.ksh
> v1='com'
> v2='net'
> v3='dk'
> v4='de'
> v5='se'
> v6='nl'
> v7='ru'
>
> echo . -type f -name "*.$v*" -print
> able:~ $ ksh test.ksh
> . -type f -name *.* -print
>
> Da du ikke applikerer nogen eval, expanderer du bare en ikke-eksisterende
> variabel $v (til en tom streng) og sætter "*." foran og "*" bagved. Det
> er også et fint argument til find, som bare finder alle filer med "." i

Nej det findet alle filer fra hvor jeg staar "." og ned, med
'hvilketsomhelstnavn.' som navn og et af variablernes vaerdi som suffix.

> navnet. Formentlig flere end du ville have. Så hvis du har kørt det script,
> har du forhåbentlig en backup at falde tilbage på, eller en anden udvej.

:)
Nu stiller jeg mig i roden af de dir. jeg vil have loebet igennem inden
jeg koerer scriptet. Ellers ja, saa ville det give nogle sjov resultater
andre steder.
Grunden til jeg stiller mig i roden af de paagaeldende dir's er netop
det som du selv paapeger og eftersom der er tale om flere nameservere
med flere strukturer til hhv. master, slave og disses individuelle
view's, saa er det umiddelbart nemmeste/sikreste loesning.

Jeg bruger lidt det samme hvis jeg vil have samme timestamp paa alle
filer i et trae.
$ cd /path/to/target
$ find . -exec touch -afmc -t 200510060018.00 {} \;

>
> Det du *vil* er så vidt jeg kan se at producere en find som på en gang
> traverserer dit træ og finder alle filer der ender på et af de angivne
> TLDer,
> så du ikke skal traversere hele træet en gang for hver TLD.

Korrekt.

>
> find er et program, og det kender ikke noget til ksh-variable eller
> arrays. De
> bliver expanderet af shellen. Shellen expanderer også wildcard "*" med
> mindre
> intet matcher. (Prøv selv:
> echo *
> giver filerne i current dir
> echo *.duharingenfilveddettenavn
> giver
> *.duharingenfilveddettenavn)
>
> I stedet har find mulighed for at bruge komplekse udtryk som argument,
> udtryk
> som den selv fortolker. se find(1) i TFM.
>
> Så du har brug for dette:
> echo $(for i in com net dk de se nl ru ; \
> do echo -name "*.$i" -print -o ; done) -type f -prune
>
> for at lave den parameterliste som du faktisk vil bruge til find.
> (Det sidste -type f -prune er blot mit bedste bud på en no-op for at
> kunne printe et overskydende -o uden problemer.)

En anden maade at skaere kagen (altid rart med lidt inspiration).

>
> Der er eet problem, ovenstående virker kun hvis der ikke er noget i current
> directory som matcher - jf det om wildcard ovenfor. Skriver man i stedet

Det er der ikke; ex. $BASEDIR/master/a/abc.com

> "\*.$i", så får find desværre backslashen med. Jeg kan ikke lige gennemskue
> hvordan man undgår det problem. Quotes i shell er generelt lidt tricky.
> En mulighed er at lave et tomt dir, hoppe ind i det og så bruge find ..:
> mkdir .foo.$$
> cd .foo.$$
> find .. $(for i in com net dk de se nl ru ; \
> do echo -name "*.$i" -print -o ; done) -type f -prune|while read f ; do ...
> done
> cd .. ; rmdir .foo.$$
> (Man kan selvfølgelig bruge en anden sti end .. som første argument til
> find, pointen at der hvor man *står* må der ikke være noget der matcher.)
> Hvis der er nogen der ved hvordan man skal sætte nogle quotes i $(...)
> udtrykket så det virker rigtigt, vil jeg gerne se det!
>
> Alternativt ville jeg nok bruge en anelse Perl i stedet. Eller simpelthen
> bare:
>
> find . -type f |grep -E '\.(com|net|dk|de|se|nl|ru)$'|while read f ; do
> ... done

Det kunne man ogsaa.

>
> (Jeg håber det var til en smule hjælp for dig eller andre!)

Du skal have mange tak for dit svar. Som sagt virker mit script, men jeg
saetter altid stor pris paa en fyldigt og velargumenteret svar og saa
synes jeg dit parameterliste bud var baade anderledes taenkt og
inspirerende. Tak for svaret Lasse.

/per
per@xterm.dk

>
> -Lasse
>



This archive was generated by hypermail 2b30 : Wed 15 Nov 2006 - 18:24:53 CET