Re: Doppelt vorhandene Dateien suchen
Dennis Neumeier wrote:
Ich habe auf meinen Linux-PC ein Verzeichnis, in dem ich alle Songs meines IPods als Sicherung daruf habe. Die Ablage-Struktur sieht folgendermaßen aus:
.../ipod-backup/bandname/albumname/liedname.mp3
Nun habe ich bemerkt, daß ich aus irgendwelchen Gründen einige Lieder einiger Alben doppelt vorhanden habe. Ich würde nun gerne ein Skript haben, daß den ganzen ipod-backup-Pfad rekursiv nach unten durchsucht und mir dann entwender direkt in einer Shell oder - besser noch - in einer Datei alle doppelt vorkommenden Lieder (top wäre hier der ganze Pfad!) ausgibt.
Kann man sowas überhaupt mit einem Shell-Skript machen? Wenn ja, wie?
Wenn Dir die Songnamen reichen: find . -type f -name \*mp3 -printf "%f\n"|sort|uniq -c | grep -vE "^ *1 " gibt dir alle Dateien *.mp3 aus, die mehr als einmal vorkommen. Die Anzahl steht dabei vor dem Dateinamen. Andreas
find . -type f -name \*mp3 -printf "%f\n"|sort|uniq -c | grep -vE "^ *1 "
Nun, das hilft zumindest mal ein wenig. Allerdings ist es bei der Anzahl von Liedern manchmal schon schwer, dann das entsprechende Verzeichnis rauszufinden. Ich könnte jetzt natürlich nach den entsprechenden Liedern in einem zweiten find-Kommando suchen, aber kann man das nicht irgendwie kombinieren? Gruß, Dennis
Dennis Neumeier schrieb:
find . -type f -name \*mp3 -printf "%f\n"|sort|uniq -c | grep -vE "^ *1 "
Nun, das hilft zumindest mal ein wenig. Allerdings ist es bei der Anzahl von Liedern manchmal schon schwer, dann das entsprechende Verzeichnis rauszufinden. Ich könnte jetzt natürlich nach den entsprechenden Liedern in einem zweiten find-Kommando suchen, aber kann man das nicht irgendwie kombinieren?
Gruß, Dennis
find . -type f -name \*mp3 -printf "%f\n"|sort|uniq -c | grep -vE "^ *1 "|cut -d\ -f 8- | while read lied; do find . -name "$lied"; echo; done
find . -type f -name \*mp3 -printf "%f\n"|sort|uniq -c | grep -vE "^ *1 "|cut -d\ -f 8- | while read lied; do find . -name "$lied"; echo; done
Danke! Genau das ist es, was ich gesucht habe! Den Rest (also Ausgabe in Datei) bekomm ich alleine hin! Gruß, Dennis
Hallo, Am Don, 28 Sep 2006, Dennis Neumeier schrieb:
find . -type f -name \*mp3 -printf "%f\n"|sort|uniq -c | grep -vE "^ *1 "|cut -d\ -f 8- | while read lied; do find . -name "$lied"; echo; done
Danke! Genau das ist es, was ich gesucht habe! Den Rest (also Ausgabe in Datei) bekomm ich alleine hin!
Ist aber ziemlich umstaendlich. Fuer sowas ist Perl einfach praktischer: ==== #!/usr/bin/perl -s use strict; use warnings; use File::Find; # den Schalter f setzen, falls nicht angegeben. Siehe perldoc perlrun # die Option "-s". $::f ||= 0; my %files; # Filterfunktion fuer File::Find::find(), siehe perldoc File::Find sub wanted { # nur Dateien und *.mp3 oder *.ogg -f && $_ =~ /\.(?:mp3|ogg)/ || return; ## Anpassung des Dateinamens fuer die Verwendung als "key", falls ## noetig Beispiel: bei mir heissen die Files ## CODE-TRACK-TITEL.(mp3|ogg) zum Vergleichen muessen CODE-TRACK und ## die Dateiendung weg. Ausserdem ist die Gross- und Kleinschreibung ## nicht einheitlich # TITEL aus dem Namen rausfischen und (ueber \L) in Lleinbuchstaben # wandeln. s/\w+-\d+-(.*)\.(?:mp3|ogg)$/\L$1/; # Sonderzeichen durch "_" ersetzen, da auch nicht einheitlich s/[^\d\w]/_/g; # den Dateinamen mit Pfad im Hash '%files' speichern, Schema # NORMIERTER_TITEL => Dateiname push( @{ $files{$_} }, $File::Find::name); } #################################################################### # "." als default-Suchpfad, falls Argumente ubergeben werden, so # werden diese als zu durchsuchende Ordnernamen interpretiert. Eine # Option "-f" wurde ggfs. entfernt. scalar @ARGV || push(@ARGV, "."); # Dateien suchen, filtern mit obigem "sub wanted" find( { wanted => \&wanted, follow => $::f }, @ARGV); # die Dubletten sortieren und ausgeben. foreach ( sort grep( $#{$files{$_}}, keys %files ) ) { foreach my $f ( @{$files{$_}} ) { print "$_\t=> $f\n"; } } ### etwas "leichter" nachzuvollziehen, aber etwas langsamer: # # sortieren und die Dubletten ausgeben. # foreach (sort keys %files) { # next unless scalar @{$files{$_}} > 1; # foreach my $f ( @{$files{$_}} ) { # print "$_\t=> $f\n"; # } # } 1; ==== Das ganze laesst sich eben prima anpassen, seien es Filterkritieren, oder was als Dublette behandelt wird. -dnh -- I am the "ILOVEGNU" signature virus. Just copy me to your signature. This message was infected under the terms of the GNU General Public License.
Am Don, 28 Sep 2006, Dennis Neumeier schrieb:
find . -type f -name \*mp3 -printf "%f\n"|sort|uniq -c | grep -vE "^ *1 "|cut -d\ -f 8- | while read lied; do find . -name "$lied"; echo; done
Danke! Genau das ist es, was ich gesucht habe! Den Rest (also Ausgabe in Datei) bekomm ich alleine hin!
Ist aber ziemlich umstaendlich.
Fuer sowas ist Perl einfach praktischer:
[...]
Hi, noch einfacher gehts mit nem super Proggy: fpdupes (http://premium.caribe.net/~adrian2/fdupes.html) Läuft bei mir seit Jahren wöchentlich auf den Fileservern ohne Probleme und nimmt auch nicht allzuviel Performance ein ;-) Ein Shellskript zum autom. Löschen der doppelten Dateien kann ich Dir, wenn gewollt noch per PM zuschicken. -- Regards, Jens Strohschnitter ------------------------------------- *!!!LINUX LINUX LINUX LINUX LINUX!!!* * http://www.jens-strohschnitter.de * ------------------------------------- Set the controls for the heart of the sun -------------------------------------
Am Donnerstag, 28. September 2006 11:29 schrieb Dominik Klein:
Dennis Neumeier schrieb:
find . -type f -name \*mp3 -printf "%f\n"|sort|uniq -c | grep -vE "^ *1 " ... find . -type f -name \*mp3 -printf "%f\n"|sort|uniq -c | grep -vE "^ *1 "|cut -d\ -f 8- | while read lied; do find . -name "$lied"; echo; done
Im grep Pattern muß nach der '1' ein Tab stehen. Alternativ einfach in '^ *1\>' ändern, damit er nicht versehentlich Dateien aussortiert, die 10fach o.ä. vorkommen, d.h., deren Anzahl mit '1' beginnt. Thomas Mack
participants (6)
-
David Haller
-
Dennis Neumeier
-
Dominik Klein
-
Jens Strohschnitter
-
Kyek, Andreas, VF-DE
-
Thomas Mack