Dateien in übergeordnetes Verzeichnis verschieben und umbenennen?
Liebe Community, vor kurzem bin ich auf ein technisches Problem gestoßen: Ich habe einen großen Ordner mit vielen Unterordnern. Diese Unterordner enthalten wiederum jeweils mehrere MP3-Dateien.
Nun meine Frage: Gibt es einen einfachen Weg all diese Dateien in das übergeordnete Verzeichnis zu verschieben und automatisch umzubenennen, wenn es Dateinamen-Konflikte gibt? Z.B. als Skript (sowohl Shell als auch CMD) oder als Programm? Der endgültige Dateiname spielt dabei keine Rolle.
Ich bedanke mich schon im Voraus für alle hilfreichen Antworten.
4 Antworten
Hallo
Gibt es einen einfachen Weg all diese Dateien in das übergeordnete Verzeichnis zu verschieben und automatisch umzubenennen
So würde das wahrscheinlich funktionieren:
find /pfad/ab/wo/gesucht/werden/soll/ -type f -iname "*.mp3" -exec mv "$i" "$(echo $i | date "+%d.%m.%Y) /pfad/wohin/alles/verschoben/werden/soll/ {} \+
Linuxhase
Sorry erstmal, dass ich erst jetzt antworte, hatte aber viel um die Ohren. Habe gerade den Kommentar gesehen, habe das Problem aber mittlerweile durch manuelles Kopieren gelöst. XD
Trotzdem danke, ich merke mir das für's nächste mal!
ich vermute, das geht so nicht, aber mit einer leichten Modifikation:
Die Grundstruktur von "find" lautet (für Dateien):
find absoluter-Pfad -type f ... -exec Befehl {} \;
also sollte die eigentliche Operation, also verschieben - mit vorherigem Test auf Konflikte - in einem Script erfolgen, Grund-Elemente:
if [ -r $Ziel ]; then
mv $Quelle $Ziel$Datum-Zeit
else
mv $Quelle $Ziel
fi
Da dieses Script für jede gefundene Datei ausgeführt wird, erübrigen sich Wiederholungen im Script.
Global könnte man den Quell- und Ziel-Pfad definieren. Wo diese liegen, ist egal, solange sie sich nicht überschneiden!
Zu beachten ist außerdem, daß "find" ohne besondere Parameter rekursiv arbeitet. Details siehe unter
man find
Das ist keine vollständige Lösung, aber ein Grundgerüst.
@DeppieDave64
Wenn ich das mache, erscheint ein > am Anfang der Zeile und nichts geschieht.
Oops, mein Fehler, das Gänsefüsschen vor dem Dollarzeichen ist zu viel.
Linuxhase
muss es unbedingt nur das übergeordnete Verzeichnis sein?
Das folgende Script verschiebt alle Dateien aus einen Verzeichnis in ein anderes Verzeichnis.
Der Aufruf erfolgt so:
script-name Quell-Verzeichnis Ziel-Verzeichnis
Sollten sich Dateien mit gleichen Namen in beiden Verzeichnissen befinden, dann wird eine solche im Zielverzeichnis mit einem Präfix ( z.B 1428515843) versehen. Diese Zahl ist eindeutig und immer ein Maß für die aktuelle Zeit.
Du musst jedoch Tcl ( tclsh ) installieren. Diese Sprache gibt es für Linux und auch für Windows.
#!/bin/bash
# \
exec tclsh "$0" "$@"
if { $argv == "" } { puts "Anwendung: $argv0 Quell-Verzeichnis Zielverzeichnis " ; exit }
set src [lindex $argv 0 ]
if { ![file isdirectory $src ] } { puts "Quell-Verzeichnis $src existiert nicht oder ist kein Verzeichnis" ; exit }
set dest [lindex $argv 1 ] if { ![file isdirectory $dest ] } { puts "Ziel-Verzeichnis $dest existiert nicht oder ist kein Verzeichnis" ; exit }
set time [clock seconds ]
foreach file [glob -nocomplain $src/* ] { if { [file isdirectory $file ] } continue
set new $dest/[file tail $file ]
if { [file exists $new ] } { set new $dest/$time-[file tail $file ] }
file rename $file $new
puts "file: $file renamed to $new"
}
Das geht nicht, weil ich ja alle Dateien aus allen Unterordnern möglichst auf ein mal verschieben möchte.
entweder du erweiterst mein Programm, was aber nicht ganz so schnell gehen würde oder aber du ermittelst alle Unterverzeichnisse
cd "ins-start-Verzeichnis
find $PWD -type d > liste_der_unterverzeichnisse
diese Liste editierst du so, dass vor jedem darin aufgelisteten Verzeichnis der Name des tclsh-Scripts und nach dem Verzeichnis das Zielverzeichnis steht.
etwa so:
programm-von-guenterhalt 1.gefundenes-Verzeichnis Zielverzeichnis
programm-von-guenterhalt 2.gefundenes-Verzeichnis Zielverzeichnis
....
programm-von-guenterhalt letztes.gefundenes-Verzeichnis Zielverzeichnis
Das werden dann sicher nicht mehr als 100 Zeilen sein.
So etwas editiere ich mit joe und seiner Lern-Funktion in weniger als einer Minute.
Die fertige Datei muss dann nur noch ausführbar sein:
chmod 755 "fertige-Datei"
und gestartet werden (wenn du vollständige Pfade für die Verzeichnisse angegeben hast, spielt das PWD keine Rolle)
./fertige-Datei
Das sollte der schnellste Weg sein. Für ein Programm mit rekursiven Funktionsaufrufen würde ich schon einige Stunden ( mit Qualitätstest) benötigen. Das müsste du schon selbst erledigen.
Hier mal als Idee, ungetestet einfach mal nur so zusammengeschrieben. Bitte erst mit Option "-t" ausprobieren (Testmodus) und am besten auch zunächst auf einer Testbenutzerkennung mit harmlosem Verzeichnis. :-)
#!/bin/sh
if [ "x$1" = "x-t" ]
then
testmode=echo
shift
fi
if [ "x$2" = "x" ]
then
echo 'usage: moveall [-t] sourcedir testdir' 1>&2
exit 1
fi
sourcedir="$1"
destdir="$2"
goterr=0
find $sourcedir -type f -print |
while read filename
do
destname=`echo "$filename" | sed 's/\//-/g'`
$testmode mv "$filename" "$destdir/$destname"
if [ $? -ne 0 ]
then
goterr=1
fi
done
exit $goterr
Du solltest Dir halt vorher nochmal die Generierung der Zieldateinamen anschauen und ggf. Deinen Wünschen anpassen.
Das Beispielskript klopft die Pfad-/Dateinamen einfach flach. Also nehmen wir an, Du hast in Verzeichnis "inputdir" die Unterverzeichnisse "subdir" und "anderesdir". Und es gebe subdir/datei1.mp3 und anderesdir/datei2.mp3. Dann kommen als Dateinamen raus:
inputdir-subdir-datei1.mp3 inputdir-anderesdir-datei2.mp3
Die Dateinamen werden ziemlich lang, wenn Du tiefe Schachtelung hast. Dafür ist der Mechanismus aber (nahezu) kollisionsfrei.
Man kann sich auch andere Wege der Zielnamensgenerierung vorstellen. Zum Beispiel mit Laufnummer.
Wichtig noch für das Skript: Das Zielverzeichnis muss vorher manuell angelegt werden. Das Skript macht das nicht selbst.
Was genau muss ich dann vorher machen? Wenn ich es so wie es ist ausführe, bekomme ich "Keine Berechtigung", auch als root.
Das ist ein Shellskript. Packe das in eine Textdatei, speichere die ab und setze mit
chmod 755 dateiname
ein "x"-Bit drauf. Dann kannst Du es ausführen.
Allerdings empfehle ich dringend, das im ersten Anlauf NICHT unter "root" durchzuführen, sondern erstmal unter einer harmlosen Benutzerkennung mit Testdaten.
Wie bereits oben geschrieben: ich hab' das Ding hier einfach mal so reingehämmert, aber auch nicht getestet. Es SOLLTE halt funktionieren, mehr nicht...
Dateikonflikte bekommen die Endung .neu
for i in *; do if [ -e ../$i ]; then mv $i ../$i.neu; else mv $i ../; fi; done
cheers | barnim
Wenn ich das mache, erscheint ein > am Anfang der Zeile und nichts geschieht. Habe ich etwas falsch gemacht? Die Ordner befinden sich alle auf dem USB-Stick "KINGSTON", der korrekt gemountet ist.