Dateien in übergeordnetes Verzeichnis verschieben und umbenennen?

4 Antworten

Vom Beitragsersteller als hilfreich ausgezeichnet

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

Woher ich das weiß:eigene Erfahrung – Ich benutze seit 2007 Linux und habe LPIC101 und LPIC102

DeppieDave64 
Beitragsersteller
 09.05.2015, 13:39

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!

GWBln  09.04.2015, 12:58

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 
Beitragsersteller
 09.04.2015, 07:03

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.

find /media/david/KINGSTON/ -type f -iname "*.mp3" -exec mv "$i" "$(echo $i | date "+%d.%m.%Y) /media/david/KINGSTON/ {} \+ 
Linuxhase  09.04.2015, 19:23
@DeppieDave64

@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"

 }


    
Woher ich das weiß:Berufserfahrung – openSuSE seit 1995

DeppieDave64 
Beitragsersteller
 09.04.2015, 07:08

Das geht nicht, weil ich ja alle Dateien aus allen Unterordnern möglichst auf ein mal verschieben möchte.

guenterhalt  09.04.2015, 12:37
@DeppieDave64

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


DeppieDave64 
Beitragsersteller
 08.04.2015, 19:01

* testen! 😝

dan030  08.04.2015, 19:32
@DeppieDave64

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.

DeppieDave64 
Beitragsersteller
 09.04.2015, 07:14
@dan030

Was genau muss ich dann vorher machen? Wenn ich es so wie es ist ausführe, bekomme ich "Keine Berechtigung", auch als root.

dan030  10.04.2015, 09:26
@DeppieDave64

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...

DeppieDave64 
Beitragsersteller
 08.04.2015, 19:00

Danke, werde ich so bald wie möglich mal testen?

Dateikonflikte bekommen die Endung .neu

for i in *; do if [ -e ../$i ]; then mv $i ../$i.neu; else mv $i ../; fi; done

cheers | barnim