Hjälp mig hitta rätt kommando för att rensa bort ett ton av filer

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Apr 2013

Hjälp mig hitta rätt kommando för att rensa bort ett ton av filer

Hej sweclockers!

Jag behöver hjälp att ta bort ett antal gamla backupper som skapats då jag reparerat information från gamla diskar. Dessa ligger utspridda i ett antal mappar från gamla installationer av Windows. Antalet filer och mappar handlar om extrema antal, vilket gör att bara lista mapparna i en fil skulle handla om flera GB.

Eftersom inga filer har blivit raderade när dom sammanfogats i Windows så finns det flera filer med "samma namn" enligt logiken

filnamn.ext
filnamn (2).ext
filnamn (3).ext
osv...

kommandot find startdir -iname "*(?)*" -delete raderar alla filer som har indikeringen att det är en "onödig" bakup. Det jag behöver göra före detta är att hitta alla filer som inte har motsvarande "filnamn.ext" så att "filnamn (2).ext" blir omdöpt. Har provat med olika från find, perl, for, if, rename, sed etc men får inte det resultat jag vill ha.

Måste ha ett kommando som fungerar i underkataloger då det handlar om tusentals kataloger i varandra.

Så kort sagt; hur får man bort alla filer med en onödig parentes i namnet och samtidigt garanterat att minst en av varje blir kvar?

Server: AMD Ryzen 7 1800X 8/16 | ASUS Crosshair VI hero | 64 GB Corsair RAM @3000 MHz | ASUS radeon RX 460 2GB | Samsung 960 PRO 512 GB M.2 | 2x 2 TB Samsung 850 PRO SSD | 6x Seagate 10 TB | NEC PA301W @ 2560x1600 | Linux Mint 19 Cinnamon

Trädvy Permalänk
Medlem
Plats
Säter
Registrerad
Apr 2005

Jag har använt rmlint för att rensa ur min hårddisk. Det fungerade fint (tror jag). Jag har inte märkt att nåt jag ville ha kvar har försvunnit.
http://rmlint.readthedocs.org/en/latest/
Kika om det kan vara nåt som kan hjälpa dig.

///

Trädvy Permalänk
Forumledare
Registrerad
Okt 2002

Från kataloger som innehåller minst en fil på formen filnamn.ext eller filnamn (#).ext där # är ett tal: se till att alla kataloger innehåller en fil på den första formen som kan döpas om från den andra formen.

Följande borde fungera att köra i Bash:

shopt -s globstar; for i in baskatalog/**/*\ \(*\).ext; do mv -- "$i" "${i% (*).ext}.ext"; done

Detta letar upp varje fil som slutar på filnamn (#).ext och döper om den till filnamn.ext i samma katalog som den funna filen ligger. I praktiken gör detta att det "högsta" tillgängliga filnumret kommer ersätta alla lägre nummer, men om du vet att alla sådana numrerade kopior är identiska (vilket du ändå i någon mån antar när du vill använda numrerade kopior för att ersätta icke-existerande onumrerade varianter) så är detta inget problem.

"Testsvit":

$ ls -R .: A B C D E F G H I J K ./A: filnamn (2).ext filnamn (3).ext filnamn.ext ./B: filnamn (2).ext filnamn (3).ext ./C: filnamn.ext ./D: filnamn (3).ext filnamn.ext ./E: filnamn (3).ext ./F: annat filnamn (2).ext annat filnamn (3).ext annat filnamn.ext filnamn (2).ext filnamn (3).ext filnamn.ext ./G: annat filnamn (2).ext annat filnamn (3).ext filnamn (2).ext filnamn (3).ext ./H: annat filnamn.ext filnamn.ext ./I: annat filnamn (3).ext annat filnamn.ext filnamn (3).ext filnamn.ext ./J: annat filnamn (3).ext filnamn (3).ext ./K: A B C D E F G H I J ./K/A: filnamn (2).ext filnamn (3).ext filnamn.ext ./K/B: filnamn (2).ext filnamn (3).ext ./K/C: filnamn.ext ./K/D: filnamn (3).ext filnamn.ext ./K/E: filnamn (3).ext ./K/F: annat filnamn (2).ext annat filnamn (3).ext annat filnamn.ext filnamn (2).ext filnamn (3).ext filnamn.ext ./K/G: annat filnamn (2).ext annat filnamn (3).ext filnamn (2).ext filnamn (3).ext ./K/H: annat filnamn.ext filnamn.ext ./K/I: annat filnamn (3).ext annat filnamn.ext filnamn (3).ext filnamn.ext ./K/J: annat filnamn (3).ext filnamn (3).ext $ shopt -s globstar; for i in **/*\ \(*\).ext; do mv -- "$i" "${i% (*).ext}.ext"; done $ ls -R .: A B C D E F G H I J K ./A: filnamn.ext ./B: filnamn.ext ./C: filnamn.ext ./D: filnamn.ext ./E: filnamn.ext ./F: annat filnamn.ext filnamn.ext ./G: annat filnamn.ext filnamn.ext ./H: annat filnamn.ext filnamn.ext ./I: annat filnamn.ext filnamn.ext ./J: annat filnamn.ext filnamn.ext ./K: A B C D E F G H I J ./K/A: filnamn.ext ./K/B: filnamn.ext ./K/C: filnamn.ext ./K/D: filnamn.ext ./K/E: filnamn.ext ./K/F: annat filnamn.ext filnamn.ext ./K/G: annat filnamn.ext filnamn.ext ./K/H: annat filnamn.ext filnamn.ext ./K/I: annat filnamn.ext filnamn.ext ./K/J: annat filnamn.ext filnamn.ext

Dold text

Det skulle uppstå problem ifall det fanns kataloger som var döpta efter samma mönster som de numrerade filerna (dvs slutade med (#).ext). Jag antar att detta inte är relevant, men ifall det skulle vara ett problem så skulle man kunna lägga in ett test likt:

shopt -s globstar for i in baskatalog/**/*\ \(*\).ext; do [ -d "$i" ] && continue j="${i% (*).ext}.ext" [ -d "$j" ] && continue mv -- "$i" "$j" done

I detta fall så känns det dock odefinierat om filer eller kataloger borde få prioritet, så sådana eventuella konflikter borde nog snarare försöka lösas manuellt.

Om du vill låta existerande onumrerade filer ha prioritet över numrerade varianter, och lägre nummer ha prioritet över högre, så kan man köra filflyttningarna i två omgångar och använda --no-clobber/-n-alternativet för mv:

shopt -s globstar; for i in baskatalog/**/*\ \(*\).ext; do mv -n -- "$i" "${i% (*).ext}.ext"; done

Efter en sådan körning så ska det inte finnas några saknade onumrerade filer där det fanns numrerade att tillgå, men i det fall det fanns multipla filer så kommer det finnas minst en numrerad kopia kvar. Dessa kan dock tas bort med find likt du tidigare noterade, i stil med

find baskatalog -name '* (*).ext' -delete

För den som undrar så vore ovanstående att föredra framför shopt -s globstar; rm -- **/*\ \(*\).extfind-anropet inte begränsas av ARG_MAX (kör getconf ARG_MAX för att se nuvarande skals gräns (ungefärligen — man behöver räkna bort miljövariabler…)) vilket potentiellt skulle kunna vara ett problem ifall det handlar om många filer. Detta ska inte vara något problem i den tidigare for-loopen, då for är en "shell built-in" och inte ett externt kommando som anropas via exec-familjen.


Se till att alltid ha en backup av filerna innan liknande större filändrande kommandon körs, eller åtminstone att köra kommandot på små kontrollerade delmängder innan de släpps helt fria. Ett vanligt "trick" är att under en testomgång sätta ett väl placerat echo framför kommandon som tänkt utföras för att se vad som är på väg att ske.

Nu med kortare användarnamn, men fortfarande bedövande långa inlägg.