staging.inyokaproject.org

Alle Ordner mit nur einer Datei löschen

Status: Ungelöst | Ubuntu-Version: Ubuntu 22.04 (Jammy Jellyfish)
Antworten |

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 Team-Icon

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 Team-Icon

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 Team-Icon

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 Team-Icon

Wikiteam
Avatar von karzer

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 Team-Icon

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
Avatar von fleet_street

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 Team-Icon

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 Team-Icon

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

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Ich würde das anders angehen.

1
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:

1
2
3
4
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.

Antworten |