Nieuws:

Welkom, Gast. Alsjeblieft inloggen of registreren.
Heb je de activerings-mail niet ontvangen?

Auteur Topic: hulp om bash script te versnellen  (gelezen 3684 keer)

hulp om bash script te versnellen
« Gepost op: 2008/12/02, 20:15:46 »
Ik ben sinds 2 maanden met Linux begonnen, na jarenlang windows gebruikt te hebben. Meteen begonnen met "programmeren" in bash om een aantal zaken zoals backups te automatiseren. Ik heb ook een script gemaakt dat men foto-bestanden converteert naar de voor mij gewenste naamgeving. Ik weet dat hier kant en klare tools voor bestaan maar dit is ook als programmeer-oefening voor mezelf bestemd.

Ik heb een volledig werkend script. Elke keer ik op een probleem (zoals filenames met spaties) botste, heb ik het script aangepast/uitgebreid na zoekwerk op internet.

Ik zoek een meer ervaren iemand die men script nakijkt en eventueel suggesties doet waar het beter zou kunnen. In mijn ogen is het script wel enorm traag. Het draait ongeveer 4-5 minuten om 3000 bestanden te verwerken, wat me vrij traag lijkt. Voorheen had ik een java programma dat hetzelfde deed maar op een fractie van de tijd klaar was op dezelfde pc. Hieronder wat uitleg over de werking van het script en natuurlijk het script zelf.

Er zijn 2 hoofdfolders met foto's : /home/davy/Pictures/ en /home/davy/paradise/f/

In deze hoofdfolders zitten foto's, al dan niet bewaard in subfolders. Bestanden en folders kunnen spaties in hun naam hebben. Bedoeling is dat alle bestanden als naam de datum en het uur krijgen waarop de foto gemaakt is. Dit in het formaat YYYYMMDD_HHMMSS.jpg

De folders met naam "vanalles" moet door het script overgeslagen worden.

Er wordt voor elk bestand gekeken of deze al een geldige bestandsnaam hebben. Als deze een geldige bestandsnaam heeft (dus yyyymmdd_hhmmss.jpg voorbeeld 20081202_182600), dan wordt de modification time van het bestand aangepast met de timestamp uit de filenaam, wanneer deze niet moest overeenkomen. Dit zodat de modification time altijd zou kloppen daar deze al eens kan wijzigen na overzetten tussen windows en linux.

Als het bestand geen geldige bestandsnaam heeft, wordt het bestand hernoemt naar formaat YYYYMMDD_HHMMSS.jpg door de modification time van het bestand uit te lezen.


#!/bin/bash

echo "Update timestamp (y/n)?"
read upd_ts
echo "Update filename (y/n)?"
read upd_fn

folders="/home/davy/Pictures/ /home/davy/paradise/f/"

for i in $folders
do

find $i* -type f | while read x
do
   # file without directory
   old_filename=`basename "$x"`

   # directory without file
   old_foldername=`dirname "$x"`
   if [[ "$old_foldername" = *vanalles* ]]
   then
     continue
   fi

   # filename without extension - deletes shortest match from back of string
   old_singlename=${old_filename%.*}

   # get old timestamp YYYYMMDDhhmmss
   old_timestamp=${old_singlename:0:8}${old_singlename:9:4}.${old_singlename:13:2}

   # file extension without point - deletes longest match from start of string
   old_extension=${old_filename##*.}

   # get date from filename and validate whether real timestamp
   old_filename_yyyy=${old_singlename:0:4}
   old_filename_mm=${old_singlename:4:2}
   old_filename_mm=`echo $old_filename_mm|sed 's/^0*//'`
   old_filename_dd=${old_singlename:6:2}
   old_filename_dd=`echo $old_filename_dd|sed 's/^0*//'`  # replace leading zeroes, otherwise bash thinks these are octals and fails test
   old_filename_uu=${old_singlename:9:2}
   old_filename_uu=`echo $old_filename_uu|sed 's/^0*//'`  # replace leading zeroes, otherwise bash thinks these are octals
   old_filename_mi=${old_singlename:11:2}
   old_filename_mi=`echo $old_filename_mi|sed 's/^0*//'`  # replace leading zeroes, otherwise bash thinks these are octals
   old_filename_ss=${old_singlename:13:2}
   old_filename_ss=`echo $old_filename_ss|sed 's/^0*//'`  # replace leading zeroes, otherwise bash thinks these are octals
   old_filename_strip_underscore="$(echo $old_singlename | sed 's/_//g')"
   old_filename_strip_numerics="$(echo $old_filename_strip_underscore | sed 's/[0-9]//g')"

   file_name_valid=0
   old_filename_len=`echo "$old_filename_strip_underscore" | awk '{print length}'`

   if [[ $old_filename_len != 14 ]]
     then file_name_valid=0
     elif [[ ! -z "$old_filename_strip_numerics" ||
         $old_filename_strip_underscore -lt 20000000000000 ||
         $old_filename_strip_underscore -gt 21000000000000 ||
         $old_filename_yyyy -lt 2000 ||
         $old_filename_yyyy -gt 2020 ||
         $old_filename_mm -lt 1 ||
         $old_filename_mm -gt 12 ||
         $old_filename_dd -lt 1 ||
         $old_filename_dd -gt 31 ||
         $old_filename_uu -lt 0 ||
         $old_filename_uu -gt 23 ||
         $old_filename_mi -lt 0 ||
         $old_filename_mi -gt 59 ||
         $old_filename_ss -lt 0 ||
         $old_filename_ss -gt 59 ]]
     then
        file_name_valid=0
     else
        file_name_valid=1
   fi

   new_filename=$(date -r "$x" +%Y%m%d_%H%M%S.$old_extension)
   new_fullfilename=$old_foldername/$new_filename

   if [[ "$file_name_valid" = 1 && "$old_filename" != "$new_filename" ]]
   then
      echo "File $old_filename will be restamped to $old_timestamp"
      if [[ "$upd_ts" = "y" ]]
         then touch -t $old_timestamp "$x"
      fi
   fi

   if [[ "$file_name_valid" = 0 ]]
   then
      echo "File $old_filename will be renamed to $new_filename"
      if [[ "$upd_fn" = "y" ]]
      then
         if [[ -f "$new_fullfilename" ]]; then
            echo "New file already exists : $new_fullfilename"
            else
              mv "$x" "$new_fullfilename"
         fi
      fi
   fi

done
done

exit 0