script för att flytta filer

Här diskuterar vi skal, kommandon och klassiska linuxverktyg.
Användarvisningsbild
Dimi
Inlägg: 703
Blev medlem: 24 dec 2006, 00:04
OS: Ubuntu
Utgåva: Vet inte/ingen utgåva passar
Ort: Stockholm

script för att flytta filer

Inlägg av Dimi »

Hej! jag arbetar med ett script där jag vill undersöka vilka underkataloger till mappen /home/mats/transmission/complete/ innehåller mp3-låtar. Om de gör det så vill jag att de flyttas till /media/trekstor/audio/music/zzslask/

Hittills så har jag lyckats få ihop följande:

Kod: Markera allt

#!/bin/bash

cd "/home/mats/transmission/complete"
find . -type f | while IFS= read filename; do #
  case "${filename,,*}" in  # ignorerar känslighet för versaler
     *mp3*)           mv "$filename" "/media/trekstor/audio/music/zzslask/"

  esac
done


Scriptet fungerar så pass att jag flyttar mp3:orna till katalogen zzslask, men jag skulle vilja att katalogen som mp3orna ligger i flyttas också. På det sätt som jag skrivit ovan flyttas bara filerna.

Hoppas att någon orkar bemöda sig med att titta på vad som kan vara fel!
David Andersson
Inlägg: 1269
Blev medlem: 15 dec 2007, 03:20
OS: Xubuntu

Re: script för att flytta filer

Inlägg av David Andersson »

1) Det finns kommandot mkdir -p som skapar en mapp om den inte finns och inte störs av om den redan finns. Den kan man alltså använda före varje fil som kopieras, med målkatalogen som argument.

2) Varför inte låta find söka på filnamn också med -iname "*.mp3" ?

3) Case-satsen söker på *mp3*, d.v.s träffar filer med mp3 utan punkt före eller med text efter, t.ex. "This_is_not_mp3.wav". Ska det vara så?

4) Med flaggan -r till read så störs den inte av eventuella backslash i filnamn.

Förslag (ej testat)

Kod: Markera allt

#!/bin/bash

sourcetop="/home/mats/transmission/complete"
targettop="/media/trekstor/audio/music/zzslask"

cd "$sourcetop"
find . -type f -iname "*.mp3" | while IFS= read -r filename; do
     relativedir=$(dirname "$filename")
     basename=$(basename "$filename")
     mkdir -p "$targettop/$relativedir"
     mv "$filename" "$targettop/$relativedir/$basename"
done
5) Man kan lägga till nån av flaggorna --no-clobber eller --interactive till mv om man vill vara säker på att inte skriva över filer med samma namn som kanske redan finns i målkatalogen. Om det är bra, och vilken som är bäst, beror förstås på vad det är du vill ska hända. Se även --update.

6) Ett alternativ till mv kan vara rsync. Då behöver man inte heller find och while, utan rsync loopar över alla filer i angivna kataloger och kan kopiera med relativa pathen intakt och kan ta bort källfilerna när den kopierat till målfilerna. Mer flaggor kan man tala om att den bara ska kopiera vissa filer. Se flaggorna --recursive --perms --times --include och --remove-source-files. (ej testat)
Användarvisningsbild
Dimi
Inlägg: 703
Blev medlem: 24 dec 2006, 00:04
OS: Ubuntu
Utgåva: Vet inte/ingen utgåva passar
Ort: Stockholm

Re: script för att flytta filer

Inlägg av Dimi »

Tack för hjälpen!

Det blev hyggligt bra det där. Det enda problemet nu är att "original mappen återstår", men det borde väl bara att trixa lite med dirname väl, så borde jag kunna bli av med den.

Jag visste om problematiken med casesatsen med *mp3*, men hur jag än vände och vred på det så fick jag inte till det så som det du skrev det. Mycket tack för det. Jag tänkte att det scenariot du poängterar skulle kunna dyka upp. Fast jag drog slutsaten att det borde vara smått otroligt osannolikt att filen har mp3 i filnamnet och heter exempelvis wma i suffixet. Men det är klart det här är mycket bättre!

Tack för hjälpen med flaggorna för mv. Ska labba lite med det och dyka in i rsync världen. Får återkomma i ärendet. :-)
David Andersson
Inlägg: 1269
Blev medlem: 15 dec 2007, 03:20
OS: Xubuntu

Re: script för att flytta filer

Inlägg av David Andersson »

Dimi skrev:Det enda problemet nu är att "original mappen återstår", men det borde väl bara att trixa lite med dirname väl, så borde jag kunna bli av med den.
Mappen som ska tas bort är "$relativedir". Den kan man ta bort med rmdir "$relativedir", men den ska ju bara tas bort om den är tom. Koden för att testa om den är tom innan man tar bort den riskerar att dominera scriptet, och det är fult. (Huvuddelen av ett vackert script ska vara dess huvuduppgift, inte tråkig administration.) Det finns två ansatser för detta: A) gör rmdir "$relativedir" efter varje mv, utan att testa om mappen är tom. Om den inte är tom kommer rmdir ändå inte att ta bort mappen. Men det blir ett fult och onödigt felmeddelande. B) gör rmdir --ignore-fail-on-non-empty "$relativedir" efter varje mv. Det blir precis som A) fast utan onödiga felmeddelanden. Prova och se om det blir ett vackert script på det sättet.
Dimi skrev: Jag visste om problematiken med casesatsen med *mp3*, men hur jag än vände och vred på det så fick jag inte till det så som det du skrev det.
Provade du att ändra *mp3* till *.mp3 i case-satsen?

Kod: Markera allt

case "${blabla,,}" in
  *.mp3) blablabla;;
esac
Dimi skrev:/home/mats/transmission/complete
Källmappen heter "transmission", som bittorrent-klienten? Du tar väl inte bort hämtade filer? Då får du ju dålig seed/leech-kvot.
Användarvisningsbild
Dimi
Inlägg: 703
Blev medlem: 24 dec 2006, 00:04
OS: Ubuntu
Utgåva: Vet inte/ingen utgåva passar
Ort: Stockholm

Re: script för att flytta filer

Inlägg av Dimi »

Det blev fint! Tack så mycket. Verkligen riktigt uppskattat att du engagerat dig så i detta. Nu visadar det så sklart inte vara så enkelt ändå. Ofta innehåller mapparna mer än bara mp3orna, det brukar ju vara en text fil, kanske någon album art och så vidare. Om de innehåller det så raderas inte mappen. Som jag ser det finns det då typ två alternativ som är okejiga. Det är att eventuellt flytta filerna till relativedir eller så raderas relativedir med de filerna i. När jag försökt trixa till scriptet så att de övriga filerna flyttas över och således tömmer mappen följt av radering så hänger det upp sig med följande meddelande:

Kod: Markera allt

mv: inter-device move failed: `/home/mats/transmission/complete/./Blue floyd - Live 2002 miami' to `/media/trekstor/audio/music/zzslask/Blue floyd - Live 2002 miami'; unable to remove target: Is a directory
Detta meddeland blir det när jag ändrar i scriptet så det ser ut så här:

Kod: Markera allt

mv "$sourcetop/$relativedir" "$targettop"
Jag är gissar att du sitter och på en lösning för detta. Jag hoppas dock att du ger mig några dagar att klura på det hela. Det är inge kul att få hjälp med allt...

Jag tror att jag provade med *.mp3 men jag minns faktiskt inte. Jag kanske använde mig av ' eller " runt *.mp3.

Det är klart jag för eller senare tar bort nerladdade filer. Jag kan väl inte seeda hur länge som helst. När det är dags att ta bort så hinner det ju bli en del som ska tas bort och då är det skönt om det kan vara automatiserat på något sätt. Det skulle i förlängning vara stiligt om det gick att koppla scriptet till transmisson. så att det vid en viss kvot flyttar filerna.

Som sagt jag tackar för den hjälp jag fått tills vidare. :-)
Skriv svar

Återgå till "Terminalforum"