# Brauche bash/sh script [THX]

## blice

Mal ne frage an die programmierer unter euch. 

ich bräuchte nen bashcript oder .sh script daß mir einige 100 dateien zusammenschustert.

```

zip -m0 frosch.zip frosch.svg frosch.gif

```

es gibt von jeder datei 2 stück mit verschiedenen endungen, das script sollte das verzeichnis recursiv durchsuchen und immer das paar in ein zip schieben .

Danke im vorraus

Edit:kann auch in php oder python sein  :Smile: 

----------

## smg

 *blice wrote:*   

> Mal ne frage an die programmierer unter euch. 
> 
> ich bräuchte nen bashcript oder .sh script daß mir einige 100 dateien zusammenschustert.
> 
> ```
> ...

 

```
#!/usr/bin/env python

# -*- coding: utf-8 -*-

import os

import glob

path = "/home/stephan/testen"

length = len(glob.glob(path+"/*"))

input = glob.glob(path+"/*")

for x in xrange(0,length,2):

   # zip -m0 is bad imho

    format_str="zip %s %s %s"%(os.path.splitext(str(input[x]))[0]+".zip", str(input[x]), str(input[x+1]))

    print input[x], " and ", input[x+1], " => " , os.path.splitext(str(input[x]))[0]+".zip"

    os.system(format_str)

# E-O-F
```

HTH,

stephan

----------

## think4urs11

```
#!/bin/bash

for i in `find /irgendwo -regex ".*\(svg\|gif\)"`

do

zip `echo $i | cut -d. -f1` $i

done
```

*edit* gnnnaaah - zip gegen gif ausgetauscht *grummel*

----------

## smg

 *Think4UrS11 wrote:*   

> 
> 
> ```
> #!/bin/bash
> 
> ...

 

Sehr gute Lösung, muss man neidlos anerkennen.  :Smile: 

P.S.: Ich glaube das geht so nicht, du hast da einen Fehler eingebaut imho.

Bye.

----------

## De Beukelaer

```
ls | sort | sed -e 's/\.[^\.]*$//' -e 's/\ /\\\ /' | uniq | sed -e 's/\(.*\)/zip -m0 \1.zip \1.*/' | bash
```

Für Spaghettiliebhaber   :Wink: 

----------

## toralf

 *Think4UrS11 wrote:*   

> 
> 
> ```
> #!/bin/bash
> 
> ...

 ?

Der regex entspricht nicht den Vorgaben, es soll immer paarweise gezppied werden, schlußendlich verlangt zip eine Syntax in der Art "$> zip foo.zip foo.bar", Test:

```
tfoerste@n22 ~ $ mkdir foo

tfoerste@n22 ~ $ cd foo

tfoerste@n22 ~/foo $ touch bar.svg bar.gif BAR.svg BAR.gif

tfoerste@n22 ~/foo $ for i in `find /irgendwo -regex ".*\(svg\|gif\)"` ; do echo zip `echo $i | cut -d. -f1` $i ; done

find: /irgendwo: No such file or directory

tfoerste@n22 ~/foo $ for i in `find . -regex ".*\(svg\|gif\)"` ; do echo zip `echo $i | cut -d. -f1` $i ; done

zip ./bar.gif

zip ./BAR.gif

zip ./bar.svg

zip ./BAR.svg

```

----------

## smg

 *toralf wrote:*   

>  *Think4UrS11 wrote:*   
> 
> ```
> #!/bin/bash
> 
> ...

 

Hehe, also meine Lösung funktioniert, habs gerade getestet.  :Smile: 

Bye.

----------

## toralf

Unter 'ner bash wäre dies hier möglich:

```
find . -regex ".*\(svg\|gif\)" | sed 's/\.svg//g' | sed 's/\.gif//g' | sort -u | while read f; do echo zip -q $f.zip $f.*; done
```

(echo dann natürlich weglassen)

----------

## smg

 *toralf wrote:*   

> Unter 'ner bash wäre dies hier möglich:
> 
> ```
> find . -regex ".*\(svg\|gif\)" | sed 's/\.svg//g' | sed 's/\.gif//g' | sort -u | while read f; do echo zip -q $f.zip $f.*; done
> ```
> ...

 

sed Anweisungen kannste mit -e groupen => weniger forks..

----------

## toralf

 *De Beukelaer wrote:*   

> 
> 
> ```
> ls | sort | sed -e 's/\.[^\.]*$//' -e 's/\ /\\\ /' | uniq | sed -e 's/\(.*\)/zip -m0 \1.zip \1.*/' | bash
> ```
> ...

 echo cool !, verzweigt aber nicht in Unterverzeichnisse, oder ?

----------

## think4urs11

 *smg wrote:*   

> Sehr gute Lösung, muss man neidlos anerkennen. 
> 
> P.S.: Ich glaube das geht so nicht, du hast da einen Fehler eingebaut imho.

 

hmm und wo siehst du ein Problem? Hier funkktioniert das ohne Probleme.

a.svg und a.gif werden in a.zip gepackt; b.svg und b.gif in b.zip usw.

```
sepp@p4-2400  ~/test $ ls -la b*

-rw-r--r-- 1 sepp users   2 24. Aug 21:27 bla2.abc

-rw-r--r-- 1 sepp users   2 24. Aug 21:27 bla2.def

-rw-r--r-- 1 sepp users 346 24. Aug 21:31 bla2.zip

-rw-r--r-- 1 sepp users   2 24. Aug 21:28 bla3.abc

-rw-r--r-- 1 sepp users 184 24. Aug 21:31 bla3.zip

-rw-r--r-- 1 sepp users   2 24. Aug 21:28 bla.abc

-rw-r--r-- 1 sepp users   2 24. Aug 21:27 bla.def

-rw-r--r-- 1 sepp users 342 24. Aug 21:31 bla.zip

sepp@p4-2400 ~/test $ unzip -l bla.zip

Archive:  bla.zip

  Length     Date   Time    Name

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

        2  08-24-06 21:28   home/sepp/test/bla.abc

        2  08-24-06 21:27   home/sepp/test/bla.def

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

        4                   2 files

sepp@p4-2400 ~/test $ unzip -l bla2.zip

Archive:  bla2.zip

  Length     Date   Time    Name

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

        2  08-24-06 21:27   home/sepp/test/bla2.abc

        2  08-24-06 21:27   home/sepp/test/bla2.def

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

        4                   2 files

sepp@p4-2400 ~/test $ unzip -l bla3.zip

Archive:  bla3.zip

  Length     Date   Time    Name

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

        2  08-24-06 21:28   home/sepp/test/bla3.abc

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

        2                   1 file
```

----------

## smg

 *Think4UrS11 wrote:*   

>  *smg wrote:*   Sehr gute Lösung, muss man neidlos anerkennen. 
> 
> P.S.: Ich glaube das geht so nicht, du hast da einen Fehler eingebaut imho. 
> 
> hmm und wo siehst du ein Problem? Hier funkktioniert das ohne Probleme.
> ...

 

Ja? Gibst du find nen absoluten oder relativen Pfad mit? Mit nem relativen Pfad klappts hier leider nicht, sorry!

```
GNU bash, version 3.1.16(1)-release (i686-pc-linux-gnu)

Copyright (C) 2005 Free Software Foundation, Inc.

GNU find version 4.3.0

Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS 
```

Bye.

----------

## think4urs11

 *smg wrote:*   

> Ja? Gibst du find nen absoluten oder relativen Pfad mit? Mit nem relativen Pfad klappts hier leider nicht, sorry!

 

von relativen Pfaden stand auch nichts in den Anforderungen  :Wink: 

*edit* im ursprünglichen Script einen blöden Tippfehler beseitigt

----------

## smg

 *Think4UrS11 wrote:*   

>  *smg wrote:*   Ja? Gibst du find nen absoluten oder relativen Pfad mit? Mit nem relativen Pfad klappts hier leider nicht, sorry! 
> 
> von relativen Pfaden stand auch nichts in den Anforderungen 

 

Stimmt!   :Embarassed: 

----------

## think4urs11

verbesserte Version die auch mit relativen Pfaden klarkommen sollte

```
#!/bin/bash

for i in `find ../test -regex ".*\(svg\|gif\)"`

do

   j=`basename $i`

   zip `echo $j | cut -d. -f1` $j

done
```

die externen Befehle basename und cut sowie echo sind überflüssig wenn man noch ein bischen kreative bashmagic benutzt  :Wink: 

```
#!/bin/bash

for i in `find ../test -regex ".*\(svg\|gif\)"`

do

   j=${i##*/}

   k=${j%.*}

   zip $k $j

done
```

und da das ganze nicht wirklich etwas mit Support zu tun hat ... -> Diskussionsforum

----------

## blice

Jo COOl ,

Ihr seid die besten.. werde ich morgen abend gleich mal testen  :Smile: 

----------

## De Beukelaer

 *toralf wrote:*   

>  *De Beukelaer wrote:*   
> 
> ```
> ls | sort | sed -e 's/\.[^\.]*$//' -e 's/\ /\\\ /' | uniq | sed -e 's/\(.*\)/zip -m0 \1.zip \1.*/' | bash
> ```
> ...

 

*moff* überlesen   :Confused: 

Dann halt so:

```
find . -type f | sort | sed -e 's/\.[^\.]*$//' -e 's/\ /\\\ /g' | uniq | sed -e 's/\(.*\)/zip -m0 \1.zip \1.*/' | bash
```

----------

## think4urs11

zum Vergleich mal mit je 5000 gif/svg getestet

es wurde hierbei nicht wirklich gezipt sondern nur der Befehl mittels echo ausgegeben um die Unterschiede darzustellen

smg (python)

```
real    0m23.893s

user    0m7.112s

sys     0m8.705s
```

Think4UrS11 (bash ohne externe Kommandos außer find)

```
real    0m10.886s

user    0m0.504s

sys     0m0.076s
```

De Beukelaer (bash mit diversen externen Kommandos)

```
real    0m35.355s

user    0m10.293s

sys     0m15.589s
```

Vermehrtes Aufrufen von externen Befehlen bremst also vergleichsweise extrem und python ist auch nicht wirklich flott.

----------

## De Beukelaer

Think4UrS11:

...und was machst du wenn Leerzeichen in den Dateinamen / Verzeichnisnamen vorkommen?

----------

## return13

Genau wegen solchen Unterhaltungen liebe ich das Gentoo Forum....

Es ist als ob ich wie ein Fisch im Wasser schwimmen würde... 

....ach ist das schön........  :Razz: 

----------

## think4urs11

 *return13 wrote:*   

> Genau wegen solchen Unterhaltungen liebe ich das Gentoo Forum....
> 
> Es ist als ob ich wie ein Fisch im Wasser schwimmen würde... 
> 
> ....ach ist das schön........ 

 

Yepp, irgendwie fühl ich mich hier richtig  :Smile: 

 *De Beukelaer wrote:*   

> Think4UrS11:
> 
> ...und was machst du wenn Leerzeichen in den Dateinamen / Verzeichnisnamen vorkommen?

 

Mich darüber beschweren das dies (ebensowenig wie relative Pfade) nicht im Anforderungskatalog stand... *hrmpf* *grummel* *moser*  :Confused: 

aber gut, geht alles, nur Frösche hüpfen...

```
#!/bin/bash

IFS=$'\012'

for i in $(find . -regex ".*\(gif\|svg\)")

do

   j=${i##*/}

   k=${j%.*}

   zip ${i%/*}\/$k $i

done
```

der IFS sorgt dafür das Leerzeichen nicht als Trennzeichen behandelt werden

j schneidet von jedem Suchergebnis alles ab was vor dem letzten '/' steht; entspricht also basename $i

k schneidet die Extension von $j ab, entspricht also basename $i|cut -d. -f1

@De Beukelaer: Bevor du wieder meckerst ... der mögliche Spezialfall das ein Filename einen oder mehrere '.' enthält führt zu einem Archivnamen ohne 'korrekte' Extension, also ein.langer.name.gif ergibt ein Archiv namens ein.langer.name, aber funktionieren tut es trotzdem.

Interessanterweise wird das ganze übrigens auch nicht schneller wenn man statt den find x-fach auszuführen den output des find vorher in ein Array packt und das dann referenziert - irgendjemand eine Idee warum?

----------

## firefly

ich vermute das in der for-schleife das find nur einmal ausgeführt wird und dann intern die ausgabe in ein array gepackt wird.

----------

## De Beukelaer

```
<?php

mach(".");

function mach($dir)

{

    $filelist = array();

    $d = opendir($dir);

    while( $file = readdir($d))

    {

        if($file != "." && $file != "..")

        {                                     

            if(is_file($file))                

            {                                 

                $flen = strlen($file);        

                $ende = substr($file, $flen -4);

                if($ende == '.gif' or $ende == '.svg')

                {                             

                    $file = substr($file, 0, $flen-4);

                    $file = str_replace(" ", "\ ", $file);

                    array_push($filelist, $file);

                }

            }

            else

            {

                mach($dir."/".$file);

            }

        }

    }

    $filelist = array_unique($filelist);

    $d2 = str_replace(" ", "\ ", $dir);

    foreach ($filelist as $file)

    {

        echo 'zip ' . $d2 . '/' . $file . '.zip ' . $d2 . '/' . $file . ".*\n";

    }

}

?>

```

```
find . | wc -l

4659

find . -type f| wc -l

3649

```

so lang man es nur das echo macht ist es sogar schneller (rechts mit time foo > weg):

```
time Think4UrS11

real    0m1.156s       0m0.683s

user    0m0.562s       0m0.566s

sys     0m0.078s       0m0.091s

time php

real    0m0.771s       0m0.356s

user    0m0.232s      0m0.228s

sys     0m0.134s       0m0.110s
```

Versucht man allerdings irgendwas mit PHP auszuführen.... (  system("echo zip $d2/$file.zip $d2/$file.*\n");  )

real    0m7.494s

user    0m3.340s

sys     0m3.241s

aua. Also noch keine bessere Lösung :-/

P.S. sollte kein Meckern sein  :Wink: 

----------

## l3u

Sowas macht man ja auch nicht in php ;-)

Also mal unter uns: Alle Gentoo-User haben nen Knall. Nachdem das Problem gelöst ist und ein funktionierendes Script genau das tut, was es soll, wird weiterdiskutiert, welche Variante davon das selbe in weniger Millisekunden erledigen könnte.

Ich liebe euch, Leute ;-)

----------

## De Beukelaer

Hab es auch mal in C gemacht.

Mit printf ist es noch schneller als die PHP-Version. Mit system ("echo zip...") allerdings doppelt so langsam wie das in PHP. Das PHP-Script ruft pro zip-Datei nur einmal zip(echo) auf. In C ruft er für jedes .gif und .svg zip(echo) einmal auf, also doppelt so oft.

Vielleicht sollte man das ganze in zip mit einbauen um nicht immer neue Prozesse zu starten   :Wink: 

----------

## think4urs11

nachdem mir mein eigenes Script zu kryptisch wurde... einmal nach KISS-Prinzip (hoffe ich jedenfalls oder geht es _noch_ simpler?)

```
#!/bin/bash

IFS=$'\012'

find . -name \*.svg | while read i

do

   zip ${i%.svg} ${i%.svg}.gif $i

done
```

----------

## l3u

Was macht IFS=$'\012'?!

----------

## think4urs11

dafür sorgen das Leerzeichen nicht als Trenner behandelt werden, ansonsten fällt der zip auf die Nase sofern Dateiname/Verzeichnisname ein <Space> enthalten. $'\012' ist nichts anderes als \n. Wurde irgendwo mal empfohlen ersteres zu verwenden und gelegentlich mache ich ja was man mir empfiehlt.

----------

