[bash/find] shellscript krijgt de parameters niet goed

Pagina: 1
Acties:

  • Zeezicht
  • Registratie: Juni 2001
  • Laatst online: 30-01 13:02
Ik ben een shell script aan het maken (zie ook linkje) maar ik krijg het nu niet voor elkaar om find de juiste -path parameters geven.

Je kan in een string paden zetten die niet gekopieerd moeten worden. Omdat cp daar geen voorziening voor heeft wil ik find gebruiken.

code:
1
find src-dir ! -path "src-dir/pad/*" -exec cp -a {} dest-dir \;

Dit werkt als ik het zelf uitvoer, maar via een script kan ik alleen het volgende werkend krijgen:
code:
1
find src-dir ! -path "*pad*" -exec cp -a {} dest-dir \;


Blijkbaar wordt de slash / niet zo leuk gevonden.

Om de string voor de excludes te maken doe ik het volgende:
code:
1
2
3
4
5
6
7
8
9
10
11
i=0
for arg in $EXCLUDE_COPY;
do
    if [ $i -gt 0 ];
    then
        EXCLUDE_COPY_PATH_STRING="${EXCLUDE_COPY_PATH_STRING} -a ! -path \"$SRC${arg}\""
    else
        EXCLUDE_COPY_PATH_STRING=" -path \"$SRC${arg}\""
        let "i+=1"
    fi
done


$EXCLUDE_COPY is als volgt gedefineerd:
code:
1
2
3
EXCLUDE_COPY="data/*"
of meerdere
EXCLUDE_COPY="data/* data2/* data3/*"


Heeft iemand een idee hoe ik dat kan oplossen? Ik moet denk ik nog wat escapen, maar weet niet hoe. Ik heb al " \" en ' geprobeerd om het path te omhullen, maar dat mocht niet baten. Terwijl het handmatig op de cli wel lukt.

  • blaataaps
  • Registratie: Juli 2001
  • Niet online
Kun je niet beter gewoon rsync gebruiken als je dergelijke ingewikkelde kopieeracties gaat doen? :)

  • Zeezicht
  • Registratie: Juni 2001
  • Laatst online: 30-01 13:02
Ik heb geen rsync functionaliteit nodig. Alleen wil ik een aantal dir's kunnen excluden, wat heel makelijk kan met find. Alleen lukt het niet in een script.

Daarnaast wil ik ook nog bestanden die nieuwer zijn dan een bepaalde datum kopieren. En dat kan niet met rsync.

  • DeMoN
  • Registratie: Maart 2001
  • Laatst online: 06-01 23:13

DeMoN

Pastafari

Heb je ook niks aan grep -v ?

Gamertag: Cosmicv0id
"Het woord Gods is voor mij niets meer dan een expressie en het product van menselijke zwakheid. De Bijbel is een verzamelwerk van legendes die achtenswaardig zijn maar ook primitief en kinderachtig.'' - Albert Einstein


  • Zeezicht
  • Registratie: Juni 2001
  • Laatst online: 30-01 13:02
Dan moet ik de output van grep -v weer gaan voeren aan cp ofzo?! Zou kunnen, maar is een omweg die naar mijn idee niet nodig is (en misschien ook weer zo zijn problemen heeft).

Het is denk ik maar een klein probleem, hoe stuur ik find aan in een bash script.

  • Zeezicht
  • Registratie: Juni 2001
  • Laatst online: 30-01 13:02
Heeft niemand een idee hoe ik dit kan oplossen?

  • JohnR
  • Registratie: April 2003
  • Niet online

JohnR

Koffie is lekker!

In mijn KSH-scriptje werkt een commando
find /path/naar/files -type f -name \*log -exec ls {} \ in ieder geval prima. Ik zie zo snel niet waarom dit KSH-specifiek zou moeten zijn. Alleen zijn er wat dingen ge-escaped :)

/(bb|[^b]{2})/


  • Zeezicht
  • Registratie: Juni 2001
  • Laatst online: 30-01 13:02
JohnR schreef op donderdag 29 juni 2006 @ 14:38:
In mijn KSH-scriptje werkt een commando
find /path/naar/files -type f -name \*log -exec ls {} \ in ieder geval prima. Ik zie zo snel niet waarom dit KSH-specifiek zou moeten zijn. Alleen zijn er wat dingen ge-escaped :)
Het gaat mij om -path, maar dat zal niet veel verschillen van name misschien. Maar vooral dat in het gedeelte met -path ook een slash (/) zit. Dat pikt ie vanuit het script niet, maar wel op de cli.

  • serkoon
  • Registratie: April 2000
  • Niet online

serkoon

mekker.

Find heeft de optie "-prune", bedoeld om stukken van de filetree weg te laten. Dat werkt waarschijnlijk sowieso wat fijner dan "! -path". Voorbeeld:
find / \( -path /usr -prune -o -path /var -prune \)
Wat ook wel handig is, is om in een shellscript ipv 'find blablabla' even een 'echo find blablabla' te doen, zodat je ongeveer precies ziet welk commando daadwerkelijk uitgevoerd wordt. Echo zorgt er wel voor dat wat escaping wegvalt, mgoed.

  • Zeezicht
  • Registratie: Juni 2001
  • Laatst online: 30-01 13:02
Echo gebruik ik altijd wel om ff te kijken idd, maar door dat escapen gaat dat toch niet helemaal lekker. Maar ik zal dat prune eens gebruiken. Ik wist niet dat je prune op deze manier moest gebruiken...

  • Zeezicht
  • Registratie: Juni 2001
  • Laatst online: 30-01 13:02
Aaargh wil allemaal niet echt lukken. Nu doet find precies wat ie moet doen (met -prune) maar nu wil cp dat niet trekken.
cp: Onbekend bestand of map
Hij wil niet één directory/bestand per keer gevoerd worden heb ik het idee. De optie -a kan ik niet gebruiken want dat wordt alles eronder automatisch mee gekopieerd.

Is er een tooltje (of optie) die het niet uitmaakt of het een dir of file krijgt en die gewoon kopieert?

  • Z-Dragon
  • Registratie: December 2002
  • Laatst online: 14:42
Gewoon de 'r' parameter van cp?

^ Wat hij zegt.


  • JeroenE
  • Registratie: Januari 2001
  • Niet online
cp: Onbekend bestand of map
Hij wil niet één directory/bestand per keer gevoerd worden heb ik het idee.
cp kan heus wel 1 bestand kopieren hoor. Krijg je geen melding als deze: "cp: cannot create regular file `test/1/bla.txt': No such file or directory" ?
Is er een tooltje (of optie) die het niet uitmaakt of het een dir of file krijgt en die gewoon kopieert?
Alleen een directory kopieren kan cp niet. Hij zegt dan ook netjes dat hij die directory overslaat.

Als je files in (sub)directories gaat kopieren naar een ander path dan moet je wel zorgen dat die (sub)directories in dat andere path ook bestaan. Als dat niet zo is dan krijg je een melding zoals ik hierboven heb gezet. De directories kan je vrij simpel aanmaken door je find eerst te doen met -type=d en mkdir als exec-commando.

Verwijderd

'find' geeft directories en files binnen directories terug.

Bij 'mv' operaties komt het wel eens voor dat in een script als 'find . -exec mv {} \;' eerst de directory verplaatst wordt, waarna vervolgens geprobeert wordt de bestanden in de directories te verplaatsen.
Je krijgt dan een foutmelding dat 'mv' de bronbestanden niet kan vinden.

Oplossing is om aan find de optie "-depth" mee te geven, zodat eerst
- de meest diepgelegen files worden teruggegeven,
- daarna de meest diepe directory,
- daarna de op-1-na meest diepgelegen files,
- daarna ....

Ook kun je 'find . -type f' of 'find . -type d' gebruiken om directories en files apart te behandelen (let op: 'type -l' bestaat ook).

Aangezien je 'cp' gebruikt in plaats van 'mv' lijkt me dit alles onwaarschijnlijk.
Het zou helpen als je iets meer informatie omtrent je script / de foutmelding zou kunnen delen.

Cheers,

  • Zeezicht
  • Registratie: Juni 2001
  • Laatst online: 30-01 13:02
jeroene schreef op dinsdag 04 juli 2006 @ 12:58:
[...]
cp kan heus wel 1 bestand kopieren hoor. Krijg je geen melding als deze: "cp: cannot create regular file `test/1/bla.txt': No such file or directory" ?
Ja foutje, ik bedoelde eigenlijk alleen de dir's.
[...]
Alleen een directory kopieren kan cp niet. Hij zegt dan ook netjes dat hij die directory overslaat.

Als je files in (sub)directories gaat kopieren naar een ander path dan moet je wel zorgen dat die (sub)directories in dat andere path ook bestaan. Als dat niet zo is dan krijg je een melding zoals ik hierboven heb gezet. De directories kan je vrij simpel aanmaken door je find eerst te doen met -type=d en mkdir als exec-commando.
Dat zal dan denk ik wel moeten. Vaag dat er niet een kopieer tool is die excludes ondersteunt.

  • Zeezicht
  • Registratie: Juni 2001
  • Laatst online: 30-01 13:02
Z-Dragon schreef op dinsdag 04 juli 2006 @ 12:54:
Gewoon de 'r' parameter van cp?
Dat gaat niet werken, want dir's die ge-exclude moeten worden en die onder je te kopieren root zitten worden dan meegenomen. Oftewel dan heb je gewoon alles.

Verwijderd

Elke keer opnieuw uitvoeren van de zelfde acties bij een resultaat van find lijkt me niet geheel paktisch. Wat je denk ik het beste kan doen is de resultaten van find redirecten naar een bestand. En dan vervolgens dat bestand als input gebruiken voor verdere acties.

Als je dat echt niet wil en commando's achter find wil loslaten dan kan dat via een contructie als:
code:
1
2
3
4
find /pad/naar/bron/ -iname "*mp3" | \
while read I; do
   cp -v --parent "$I" /pad/naar/doel/
done

in dit voorbeeld worden alle mp3 bestanden gekopieerd.
Maar daar kan je elke findopdracht van maken natuurlijk.

Hoop dat dit is wat je zoekt.

  • blaataaps
  • Registratie: Juli 2001
  • Niet online
En hoe precies is "op elke hit van find cp aanroepen met 1 argument" sneller dan "op elke hit van find cp aanroepen met 1 argument"?
Het performance-issue wat je probeert te bestrijden is wel reëel, maar ik zie niet in hoe jouw script daar een oplossing voor biedt, kijk eens naar xargs zou ik zeggen :)

Verwijderd

blaataaps schreef op maandag 17 juli 2006 @ 14:02:
En hoe precies is "op elke hit van find cp aanroepen met 1 argument" sneller dan "op elke hit van find cp aanroepen met 1 argument"?
Het performance-issue wat je probeert te bestrijden is wel reëel, maar ik zie niet in hoe jouw script daar een oplossing voor biedt, kijk eens naar xargs zou ik zeggen.
Jah, daar is dan wel weer iets voor te zeggen. 8)7
Pagina: 1