|
Tragoflatz
Anmeldungsdatum: 8. September 2022
Beiträge: 5
|
Hallo. Ich suche eine Möglichkeit, alle Ordner eines Verzeichnisses, in der nur eine (oder wahlweise auch zwei oder drei) Dateien vorhanden sind, zu finden und zu löschen. Beispiel 1: ./7apes/Brick & Steel/
Brick & Steel.mp3
--> Ordner 'Brick & Steel' soll gelöscht werden
Beispiel 2:
./7apes/Tales of Two Cities/
Blow.mp3
Brick & Steel.mp3
Cave of Wonders.mp3
The Ambassador.mp3
Slingshot.mp3
--> Ordner 'Tales of Two Cities' soll NICHT gelöscht werden Ich habe leider keine zeitlichen Kapazitäten, mich in Scriptsprachen einzuarbeiten, obwohl ich das gerne tun würde. Aber vielleicht hat ja jemand hier Zeit, Lust und Wissen, mir bei meinem Vorhaben zu helfen. Beste Grüße! Bearbeitet von rklm: Version → sinnvoll
|
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13242
|
Du kannst etwas bauen mit find, dirname, sort und uniq.
|
|
Tragoflatz
(Themenstarter)
Anmeldungsdatum: 8. September 2022
Beiträge: 5
|
Danke für die Anregung. Aber genau das kann ich nicht. Ich kann die Befehle einzeln nutzen, habe aber nicht den Hauch einer Ahnung davon, wie ich damit zusammenhängend mein Problem lösen.
|
|
shiro
Supporter
Anmeldungsdatum: 20. Juli 2020
Beiträge: 1303
|
rklm schrieb: Du kannst etwas bauen mit find, dirname, sort und uniq.
Ich denke, rklm möchte dich anregen, über die genannten Stichworte selbst eine Lösung zu erarbeiten und nicht einfach nur eine vorgekaute Lösung anzuwenden. Das kann zugegebener Weise etwas hart sein. Aus diesem Grund gebe ich jetzt mal eine "vorgekaute" Lösung allerdings ohne Erklärung. Dann kannst du über "man" dir anschauen, was die Parameter machen und ein wenig damit spielen und wenn du alles verstanden hast, den "ls -l" in ein "rm -f" umbauen.
find tmp/ -type f -printf "%h\0" | sort -zr | uniq -zc | sed -nz '/^[ ]*1 / s/^[ 0-9]* //p' | xargs -0 ls -l
Ich hoffe, ich habe es dir jetzt nicht zu leicht gemacht. Solltest du etwas nicht verstehen, kann ich es aber noch erklären.
|
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13242
|
shiro schrieb: rklm schrieb: Du kannst etwas bauen mit find, dirname, sort und uniq.
Ich denke, rklm möchte dich anregen, über die genannten Stichworte selbst eine Lösung zu erarbeiten und nicht einfach nur eine vorgekaute Lösung anzuwenden.
Zumal man auch bei vorgekauten Lösungen verstehen sollte, was sie tun, damit man keine unangenehmen Überraschungen erlebt.
|
|
karzer
Wikiteam
Anmeldungsdatum: 10. April 2022
Beiträge: 1575
|
rklm schrieb: Zumal man auch bei vorgekauten Lösungen verstehen sollte, was sie tun, damit man keine unangenehmen Überraschungen erlebt.
Hier wirds's zumindest nicht gefährlich; wie shiro schon schrieb muss dafür erst der relevante Teil hinter xargs geändert werden. Interessant wirds dabei, herauszufinden, was das sed macht.
|
|
shiro
Supporter
Anmeldungsdatum: 20. Juli 2020
Beiträge: 1303
|
karzer schrieb: Interessant wirds dabei, herauszufinden, was das sed macht.
Ok, wenn sed nicht so leicht zu verstehen ist, kannst du
# statt
sed -nz '/^[ ]*1 / s/^[ 0-9]* //p'
# auch
awk -v RS="\0" '$1==1{printf "%s\0",$2}'
verwenden. Eine Erklärung, was sed bzw awk machen, werde ich liefern, wenn Tragoflatz hier nachfragt. Der Lerneffekt wäre sonst zu gering, wenn vorher die Lösung kommt.
|
|
fleet_street
Top-Wikiautor
Anmeldungsdatum: 30. August 2016
Beiträge: 2400
|
shiro schrieb: Ich hoffe, ich habe es dir jetzt nicht zu leicht gemacht.
Nö, da schon ganz am Anfang ein Fehler eingebaut wurde, läuft diese vorgekaute Lösung auf ls -l des aktuellen Verzeichnisses hinaus, also nur das Kommando hinter xargs. shiro schrieb: Ok, wenn sed nicht so leicht zu verstehen ist, kannst du […] statt sed […] auch awk […] verwenden.
LOL!1 Der war gut. 😀 😊 Wenn IT-Humor zu sperrig ist, dann liegt es am Publikum. 😛 *SCNR*
|
|
shiro
Supporter
Anmeldungsdatum: 20. Juli 2020
Beiträge: 1303
|
fleet_street schrieb: *SCNR*
Sorry, das empfand ich auch, als ich die Anfrage mit Ich habe leider keine zeitlichen Kapazitäten, mich in Scriptsprachen einzuarbeiten ...
gelesen hatte. Statt die Aussage als Frechheit aufzufassen, habe ich sie als Aufforderung zum Spiel gelesen. Der Witz steckt allerdings tatsächlich in dem Part, der hinter dem xargs kommen muss, was aus meiner Sicht rklm und karzer auch gesehen haben. Aber man sollte ja einen Schritt nach dem anderen machen.
Nö, da schon ganz am Anfang ein Fehler eingebaut wurde, ...
Man kann die Aufgabe auf unterschiedliche Art angehen. In meinem Beispiel werden alle Dateien (-type f) in den unter "tmp/" liegenden Verzeichnissen gesucht und nur der Pfad zero-terminiert ausgegeben (-printf "%h\0"). Der Sort erfolgt reverse, damit "von unten" aufgeräumt werden kann. Der "uniq -c" liefert die Anzahl der Dateien in dem Verzeichnis. Mit dem sed oder awk werden alle die Einträge gelistet, die nur eine Datei im Verzeichnis haben. Dieses Ergebnis wird an xargs übergeben, um die "Löschaktion" zu starten. Das Spannende kommt dann zum Tragen, die Verzeichnisse nicht zu löschen, die unter einem als zu löschen gefundenen Verzeichnis liegen. Aber soweit sind wir noch nicht. Daher erst mal einen Schritt nach dem anderen.
|
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13242
|
shiro schrieb:
Der Sort erfolgt reverse, damit "von unten" aufgeräumt werden kann.
Da liegt ein Denkfehler vor. Das kannst Du mit sort -r nicht erreichen. Um ein Aufräumen des Baumes von unten zu erreichen, muss man anders vorgehen.
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11278
|
Tragoflatz schrieb: Ich habe leider keine zeitlichen Kapazitäten, mich in Scriptsprachen einzuarbeiten, obwohl ich das gerne tun würde. Aber vielleicht hat ja jemand hier Zeit, Lust und Wissen, mir bei meinem Vorhaben zu helfen.
Du kannst das auch in einer kompilierten Sprache schreiben - z.B. in Rust: seahawk1986/dircleaner - ein fertiges Binary für x64 gibt es hier: seahawk1986/dircleaner/releases/download/0.0.1/dircleaner_x64
|
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17630
|
Ich würde das anders angehen.
| find -type d -printf "%f " -exec bash -c "find {} -type f -printf '.' | wc -c " ";"
|
Verzeichnisse suchen (-type d) und den Namen ausgeben (-printf "%f") und dann für jedes gefundene Verzeichnis ein verschachteltes find aufrufen, dass für jede Datei einen "." ausgibt um dann mit wc die Punkte zu zählen. Das ist nötig, weil die Leute gerne Leerzeichen und Zeilenumbrüche in Dateinamen einbauen, sonst könnte man einfach die Dateinamen ausgeben (default) und die Zeilen zählen (wc -l). Eine Liste der Verzeichnisse kann man dann so machen: | find -type d -printf "%f " -exec bash -c "find {} -type f -printf '.' | wc -c" {} ";" | egrep " [012]$"
fr 0
mi 1
do 0
|
Gelöscht wird noch nichts. Gegen Zeilenumbrüche und selbst Leerzeichen im Dateinamen ist die Liste dennoch anfällig, insbes. wenn vor dem Zeilenumbruch eine Zahl < 3 steht, die per Blank vom vorherigen Teil des Dateinamens abgesetzt ist. Hier könnte es also sein, dass ein Verzeichnis existiert mit dem Namen fr mit 0 Dateien und mi mit einer Datei, oder ein Verzeichnis "fr 0\nmi" mit einer Datei. Ob in einem Verzeichnis andere Verzeichnisse liegen, Dateien, symbolische Links oder was auch immer wird nicht unterschieden (everything is a file). Ach, halt, doch, das innere find prüft auf Typ f.
|