MacMinds - great minds think different

Navigatie

Zoeken

Inloggegevens

Je bent niet ingelogd.


#1 22-02-2011 11:18

luclodder
Pro
@ Heerlen
Geregistreerd: 18-09-2006
Website

Script voor filteren bestanden nodig

Weet niet goed waar ik deze post moet plaatsen. Ik denk hier.

Wat ik nodig heb - en weet niet goed waar ik moet beginnen - is een script dat:

Uit een CSV of TXT file een nummer haalt (op elke regel staat een ander nummer)
Aan de hand van dit nummer een alle files met dit nummer kopiert van een directory naar een andere.

dus:
1234 moet de files 1234_1.jpg 1234_2.jpg 1234_3.jpg etc. kopieren!
34567 moet de files 34567.jpg 34567_1.jpg

Waarom?
Ik heb een lijst met productnummers 400+ en een dir met 100.000+ images van producten. Ik wil alleen de benodigde images uit die map kopieren.

Hebben jullie tips.
Hoe en of waar te beginnen? Automator? Bash script?


[ o ] luclodder fotografie
www.luclodder.com |
flickr | twitter/luclodder | weblog

Offline

 

#2 22-02-2011 11:37

Buzz
@ Delft
Geregistreerd: 10-10-2006

Re: Script voor filteren bestanden nodig

Zoiets is met een scriptje (in Perl, Ruby, of iets dergelijks) van 5 tot 10 regels snel voor elkaar te krijgen.

Hieronder een beginnetje in Perl. Ik heb het niet getest, en het is me ook niet helemaal duidelijk naar welke directory je de bestanden wil kopiƫren. Ik ben er vanuit gegaan dat daar het nummer uit de lijst in moet voorkomen.

Code:

#!/usr/bin/env perl
use warnings;

# Open je lijst met op elke regel een nummer
open(LIJST,"filenaam_lijst.txt"); 

 # In de foreach loop bevat de variabele $nummer elke keer het nummer dat op een nieuwe regel staat.
foreach $nummer (<LIJST>) {  
  chomp $nummer; # Strip de newline van het nummer.
  
  # Dit wordt de directory waar straks naartoe wordt gekopieerd.
  $doeldirectory = "/hier/je/doeldirectory/$nummer"; 
 
  # Als de directory nog niet bestaat wordt hij gemaakt.
  if (not -e $doeldirectory) { system "mkdir -p $doeldirectory"; } 

  # De array @bestanden bestaat uit een lijst met alle bestandsnamen van .jpg files die met $nummer beginnen.
  @bestanden = <$nummer*.jpg>;

  # Deze foreach loop gaat een voor een de gevonden .jpg bestanden af en kopieert ze naar $doeldirectory.
  foreach $bestand (@bestanden) { 
    system "cp $bestand $doeldirectory";
  }
}

Als je dit bijvoorbeeld opslaat in een bestandje "kopieer.pl", kan je het executable maken door in de Terminal het commando "chmod +x kopieer.pl" in te voeren. Vervolgens zorgt het commando "./kopieer.pl" ervoor dat het wordt uitgevoerd.

Laatst bewerkt door Buzz (22-02-2011 11:45)

Offline

 

#3 22-02-2011 12:04

luclodder
Pro
@ Heerlen
Geregistreerd: 18-09-2006
Website

Re: Script voor filteren bestanden nodig

perfect! Dank je het werkt! En snel antwoord.
Super, had zelf niet aan perl gedacht.


[ o ] luclodder fotografie
www.luclodder.com |
flickr | twitter/luclodder | weblog

Offline

 

#4 22-02-2011 12:09

luclodder
Pro
@ Heerlen
Geregistreerd: 18-09-2006
Website

Re: Script voor filteren bestanden nodig

oeps toch niet helemaal... Hij maakt steeds een dir aan met daarin de jpg files
Dus alles vele malen dubbel :-S

hij probeert ook een 3.jpg en een file met alleen het nummer te maken!

Laatst bewerkt door luclodder (22-02-2011 12:11)


[ o ] luclodder fotografie
www.luclodder.com |
flickr | twitter/luclodder | weblog

Offline

 

#5 22-02-2011 12:50

Buzz
@ Delft
Geregistreerd: 10-10-2006

Re: Script voor filteren bestanden nodig

Ik begrijp niet helemaal wat je bedoelt. Je zou je misschien zelf  in Perl moeten verdiepen om het script aan jouw situatie aan te passen.

Maar ik zie al dat als er ook kleinere nummers (zoals 3) in de lijst voorkomen die onderdeel zijn van grotere nummers (zoals 328), dan gaat het inderdaad mis.

Je zal de toekenning van de array @bestanden dan slimmer moeten maken. Dus in plaats van:

Code:

@bestanden = <$nummer*.jpg>;

Zoiets:

Code:

@bestanden = <$nummer\{,_*\}.jpg>;

Dan worden alleen de bestanden 3.jpg, 3_1.jpg, 3_2.jpg, etc. gekopieerd, als het kleine nummer 3 in de lijst voorkomt. 328.jpg, 328_1.jpg, etc. worden dan overgeslagen.

De syntax van wat er tussen de <>-haken staat is eigenlijk meer shell dan perl. In perl heet zoiets een glob. Zoals altijd in perl kan het op meerdere manieren. Dit is een vrij kort op te schrijven manier, maar misschien niet helemaal de meest inzichtelijke.

Laatst bewerkt door Buzz (22-02-2011 13:03)

Offline

 

#6 22-02-2011 15:28

Julian
Geregistreerd: 18-09-2006

Re: Script voor filteren bestanden nodig

Het aanmaken van de overtollige dir is in ieder geval makkelijk te verhelpen.

Een variant op het script van Buzz:

Code:

#!/usr/bin/env perl
use warnings;

# Open je lijst met op elke regel een nummer
open(LIJST,"filenaam_lijst.txt"); 

# Bij de aanroep van het script wordt de directory waar het heen moet als argument meegegeven.
$doeldirectory = @ARGV[0]

# Als de directory nog niet bestaat wordt hij gemaakt.
if (not -e $1) { system "mkdir -p $doeldirectory"; } 

 # In de foreach loop bevat de variabele $nummer elke keer het nummer dat op een nieuwe regel staat.
foreach $nummer (<LIJST>) {  
  chomp $nummer; # Strip de newline van het nummer.
  
  # De array @bestanden bestaat uit een lijst met alle bestandsnamen van .jpg files die met $nummer beginnen.
  @bestanden = <$nummer\{,_*\}.jpg>;  # gewijzigd zoals Buzz voorstelde

  # Deze foreach loop gaat een voor een de gevonden .jpg bestanden af en kopieert ze naar $doeldirectory.
  foreach $bestand (@bestanden) { 
    system "cp $bestand $doeldirectory";
  }
}

Hierna moet je het script dus aanroepen met
./kopieer.pl /map/waar/het/heen/moet

Offline

 

#7 22-02-2011 20:52

luclodder
Pro
@ Heerlen
Geregistreerd: 18-09-2006
Website

Re: Script voor filteren bestanden nodig

ja die overtollige dir had ik er al uit gesloopt.

Heb echter lang liggen vechten.
De export vanuit excell of de copy/paste van de kolom in teksteditor leverde een txt bestand op waar het script onzin mee uithaalde. Hij maakte steeds een .jpg copy regel aan zonder nummer er voor.

Een met de hand aangemaakte txt bestand deed het wel.

uiteindelijk werkte een txt bestand met vi gemaakt en copy/past WEL!
Heel erg vreemd!
Wat doet die chomp eigenlijk precies? Zijn er verschillende regeleinden?


[ o ] luclodder fotografie
www.luclodder.com |
flickr | twitter/luclodder | weblog

Offline

 

#8 23-02-2011 09:38

Buzz
@ Delft
Geregistreerd: 10-10-2006

Re: Script voor filteren bestanden nodig

Ja, onder UNIX, dus ook in Mac OS X is het gebruikelijk om een regel te eindigen met alleen een linefeed, ook wel newline genoemd. Dat is een speciaal onzichtbaar karakter in de file (weer te geven met \n in Perl). Als je een bestand in Textedit of vi aanmaakt dan zal dat het geval zijn. In Perl haalt chomp die linefeed aan het einde weg.

Onder DOS/Windows, dus wellicht ook als je direct uit Excel exporteert, bestaat het regeleinde uit twee karakters: een carriage return en een linefeed (\r\n).

Om daar ook van af te komen zou je kunnen proberen de chomp regel te vervangen met zoiets als dit:

Code:

$nummer =~ s/\r|\n//g;

Maar het zou wellicht ook nog kunnen dat een lege regel aan het eind van het Excel-geexporteerde bestand de .jpg file veroorzaakte. Dat soort onzichtbare dingen in je invoerbestand levert bij dit soort simpele klusjes vaak de grootste hoofdpijn op, als je er niet van weet. Om te zien welk copy commando er wanneer precies in het script wordt uitgevoerd zou je de laatste lus zo kunnen veranderen:

Code:

  foreach $bestand (@bestanden) { 
   $command = "cp $bestand $doeldirectory";
   print "-- executing the following command: $command\n";
   system $command;
  }

Offline

 

Forum voettekst

MacMinds v 1.05 Powered by PunBB