ubuntuusers.de

Ordner mit nur einer Datei auflösen und Datei einen Ordner "höher" verschieben

Status: Gelöst | Ubuntu-Version: Ubuntu 12.04 (Precise Pangolin)
Antworten |

mb59

Anmeldungsdatum:
5. Oktober 2006

Beiträge: 104

Wohnort: Sankt Poelten - Viehofen

Hallo Mitsammen!

Habe mit einem MP3 Tagging Tool, das auch Renames durchführt meine Mediathek zerschossen. Die Dateistruktur /Interpret/Album/Song.mp3 ist schon gut, aber das Tool hat mir jetzt einzelne Songs von Samplern auch in diese Struktur gebracht. Das bedeutet, dass ich viele Album-Ordner habe, in denen nur ein Song gespeichert ist. Also z.B. /Deep Purple/Sampler 1/Child in Time.mp3.

Die Idee wäre nun, dass ich diese einzelnen Datein einfach einen Ordner höher in das Interpreten-Verzeichnis verschiebe und somit die tausenden Verzeichnisse mit nur einer Datei loswerde.

Händisch wäre das eine Arbeit für die nächsten zwei Monate ☹ !!

Hat irgendwer eine Idee, wie ich das automatisieren könnte?

Danke für Eure Hilfe im Voraus

LG Michael

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17625

Wohnort: Berlin

Heißen die Ordner immer "Sampler .*"?

Muss man selbst noch feststellen, dass nur eine Datei im Ordner ist?

1
find musicroot -name "*.mp3" -execdir mv {} .. ";"

sollte (ohne diese Bedingungen) die Musik eine Etage hochschieben.

mb59

(Themenstarter)

Anmeldungsdatum:
5. Oktober 2006

Beiträge: 104

Wohnort: Sankt Poelten - Viehofen

Hallo User Unknown,

nein, die Ordner haben ganz verschiedene Namen.

Das ist ja das Problem, dass ich quasi jeden Ordner ansehen muss, ob da wirklich nur eine Datei drinnen ist... Es würde schon mal helfen, eine Liste zu erzeugen, in der alle Ordner stehen, wo nur eine Datei drinnen ist. Die könnte ich ja dann zu einem "mv .." Skript editieren.

Hier wäre eine Automatisation wirklich sehr (!!!) hilfreich.

Danke und LG Michael

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13219

Hi,

hiermit kann man alle Ordner finden, die nur eine Datei enthalten - ist allerdings nicht robust gegenüber Zeilenumbrüchen in Dateinamen:

1
$ find . -type f -exec dirname {} \; | sort | uniq -c | sed -rn 's#^[[:space:]]*1[[:space:]]##p'

Dann könnte man das so kombibieren:

1
2
$ find . -type f -exec dirname {} \; | sort | uniq -c | sed -rn 's#^[[:space:]]*1[[:space:]]##p' \
  | while read fold; do mv "$fold"/* "$fold/.."; done

Ungetestet!

Ciao

robert

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Sowas solltest Du dann doch wenigstens mit Null-terminierten Strings machen:

find . -type f -print0 -exec dirname {} \; | sort -z | uniq -cz | sed -rn 's#^[[:space:]]*1[[:space:]]##p'

sonst ist das zu heiß, wegen eventueller Leer- und Sonderzeichen ....

Edit:
Von der Performance her wird eine Lösung mit einer for- Schleife und File-Globbing wohl besser sein.
(ich gucke mal, ob ich so etwas hin bekomme ...)

LG,

track

mb59

(Themenstarter)

Anmeldungsdatum:
5. Oktober 2006

Beiträge: 104

Wohnort: Sankt Poelten - Viehofen

@rklm: Danke für den Tipp. Beispiel 1 funktioniert und zeigt mir die Verzeichnisse. Beispiel 2 verschiebt alles in mein Home-Verzeichnis ... unverändert ...

@track: Danke für Dein "gucken"! 😉

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13219

track schrieb:

Sowas solltest Du dann doch wenigstens mit Null-terminierten Strings machen:

Deshalb hatte ich ja dazu geschrieben, dass es da gewisse Unsicherheiten gibt.

find . -type f -print0 -exec dirname {} \; | sort -z | uniq -cz | sed -rn 's#^[[:space:]]*1[[:space:]]##p'

sonst ist das zu heiß, wegen eventueller Leer- und Sonderzeichen ....

Du müsstest die Ausgabe von dirname mit \0 terminieren - nicht die gefundenen Dateinamen. Also eher

1
$ find . -type f -exec bash -c 'for f; do echo -ne "$(dirname "$f")\\000"; done' -- {} + | sort -z | uniq -cz

Aber wie bekommst Du dann sed dazu, \000 als Zeilentrenner zu betrachten?

Das ganze wäre in Ruby viel einfacher... ☺

Ciao

robert

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

1.) Inzwischen habe ich mal die Sache mit File-Globbing gebastelt:

#!/bin/bash

shopt -s globstar
shopt -s nullglob				# blendet leere Fundstücke aus

for d in **/ ;  do
	i=0
	for f in "$d"* ; do
		i=$(( i+1 ))
	done
	if [ $i = 1  -a  -f "$f" ] ; then
		echo mv "$f" "$d"..
		echo rm "$d"
	fi
done

Die echo s stehen noch kontrollhalber drin. Die müssen natürlich entfernt werden, damit das Skript "scharf" wird.
Edit:
Die if - Abfrage erweitert um eine Überprüfung der Dateiart, damit er sich nicht an leeren Verzeichnissen vergreift.

2.) Wie man bei sed den Zeilentrenner ändern kann, weiß ich auch nicht. Bei bei Perl gäbe es eine Lösung, und bei awk ginge es auch.

LG,

track

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17625

Wohnort: Berlin

Okay - Musiksammlungen haben ja oft Leerzeichen im Namen, selten aber wohl Zeilenumbrüche.

Selten sollten auch Namenskollisionen sein, obwohl natürlich bei den Stones auf jeder 3. Scheibe Sympathy for the devil drauf ist (Live, Best of, ...) aber das sind dann keine CDs mit einem Stück - oder?

Also hier meine Teststruktur:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
./musik
./musik/Frank Zappa
./musik/Frank Zappa/Sampler 1
./musik/Frank Zappa/Sampler 1/fz.mp3
./musik/Janis Joplin
./musik/Janis Joplin/Sampler 1
./musik/Janis Joplin/Sampler 1/jj.mp3
./musik/Allman Brothers
./musik/Allman Brothers/Sampler 1
./musik/Allman Brothers/Sampler 1/ab.mp3
./musik/Allman Brothers/Sampler 1/ab-intro.mp3
./musik/Deep Purple
./musik/Deep Purple/Sampler 1
./musik/Deep Purple/Sampler 1/dp-intro.mp3
./onemp3.sh
./vorher.lst

fz, jj usw. damit man später wiedererkennt, wo ein Irrläufer herkommt, und vorher.lst ist genau diese Liste, und onemp3.sh ist das Hexenwerk, zu dem wir jetzt kommmen:

1
2
3
#!/bin/bash
#
(($(dir "$1"/*.mp3 | grep -c mp3) == 1)) && mv "$1"/*.mp3 "$1"/..

dir $1 ist das Verzeichnis, das der gleich vorzustellende find-Befehl findet, und da darin Leerzeichen erwartet werden maskiert. dir "$1"/*.mp3 listet also die mp3-Files darin auf, leitet sie an grep, welches mit -c zählt wieviele Muster dort mp3 enthalten.

Der Sicherheit halber: Ein Technokünstler mit dem coolen Remix mp345mp345.mp3 wird hier als 3 Songs gezählt; wenn Du vor allem solche Titel in der Sammlung hast geh zum Arzt - da kann ich nicht mehr helfen. 😉

(( ... == 1 )) prüft schlicht, ob es genau eine solche Datei gibt, wenn ja wird der mv-Befehl ausgelöst: alle mp3s (nämlich das eine) wird einen Ordner hochgepusht.

Und hier der ominöse find-Befehl:

find musik -mindepth 2 -type d -exec ./onemp3.sh {}  ";" 

Man kann den Inhalt des Bash-Scriptes nicht einfach da einfügen, wo ./onemp3.sh steht, aus mehreren Gründen: a) Verwendet das Script eine Pipe, was find nicht derart für -exec-Befehle unterstützt. b) kann find nicht ((...)) && ..., und nicht $(( ... )) und überhaupt erschreckend wenig.

Achso - das Resultat:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
./musik
./musik/Frank Zappa
./musik/Frank Zappa/fz.mp3
./musik/Frank Zappa/Sampler 1
./musik/Janis Joplin
./musik/Janis Joplin/jj.mp3
./musik/Janis Joplin/Sampler 1
./musik/Allman Brothers
./musik/Allman Brothers/Sampler 1
./musik/Allman Brothers/Sampler 1/ab.mp3
./musik/Allman Brothers/Sampler 1/ab-intro.mp3
./musik/Deep Purple
./musik/Deep Purple/dp-intro.mp3
./musik/Deep Purple/Sampler 1
./onemp3.sh
./vorher.lst

Als nächstes kann man dann die leeren Verzeichnisse noch mit

find musik -empty -delete 

wegräumen.

Vorsicht! Die Reihenfolge von -empty und -delete ist entscheident. Führt man erst -delete aus ist hinterher alles empty!

Find ist generell sensibel für Schalterreihenfolgen - manchmal spielt es keine Rolle, und dann kann man fälschlich den Eindruck gewinnen, das wäre allgemein so; auch weil es allenthalben bei anderen Programmen so ist.

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Ja, über solche skurrilen Sonderfälle hatte ich auch nochmal nachgedacht, und mein Skript oben nachgebessert.
(damit er nicht Verzeichnisse misshandelt, die 1 Unterverzeichnis drin haben statt einer Datei !)

Wenn allerdings im übergeordneten Verzeichnis der Name schon mal existiert, läuft das Verschieben auf eine Fehlermeldung, und das Löschen anschließend auch. Somit passiert also auch da nichts Schlimmes.

track

mb59

(Themenstarter)

Anmeldungsdatum:
5. Oktober 2006

Beiträge: 104

Wohnort: Sankt Poelten - Viehofen

Danke für "das Anstrengen der grauen Zellen" und die "Entwicklungsarbeit"!!!!!!!!

Komme (leider) erst morgen zum Ausprobieren. Melde mich dann sofort!

LG Michael

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17625

Wohnort: Berlin

Morgen sind die Antworten nicht mehr gültig. ☺

mb59

(Themenstarter)

Anmeldungsdatum:
5. Oktober 2006

Beiträge: 104

Wohnort: Sankt Poelten - Viehofen

Hat heute Gott sei Dank doch noch funktioniert 😉

Danke! Ihr habt mir viel Arbeit erspart!!!!

LG Michael

Antworten |