Enkelt bashskript - Någon som vill hjälpa mig

Permalänk
Medlem

Enkelt bashskript - Någon som vill hjälpa mig

Hej
Jag skulle behöva lite jälp emd att skriva ett enkelt bash-skript.
Skriptet skall ta en bild med min kamera och sedan överföra den till en valfri plats.
Jag vill kunna köra skriptet såhär: takeimg [sökvag]
Om ingen sökväg är specifierad så skall dem hamna i en defaultmapp.

Okej, nu börjar vi.
För att ta en bild så körs detta kommando:
>gphoto2 --capture-image
Bilden lagras då på minneskortet på kameran
För att lista alla filer på minneskortet så körs kommandot:
>gphoto2 -L
Det blir då den sista bilden som finns i den listan som jag vill överföra till en katalog på datorn.
Ett exempel på utdatan från ovanstående kommando är:

Det finns inga filer i mappen '/'. Det finns inga filer i mappen '/store_00010001'. Det finns inga filer i mappen '/store_00010001/DCIM'. Det finns 186 filer i mappen '/store_00010001/DCIM/100NCD50': #180 DSC_0179.JPG 898 KB 2256x1496 image/jpeg #181 DSC_0180.JPG 889 KB 2256x1496 image/jpeg #182 DSC_0181.JPG 900 KB 2256x1496 image/jpeg #183 DSC_0182.JPG 908 KB 2256x1496 image/jpeg #184 DSC_0183.JPG 914 KB 2256x1496 image/jpeg #185 DSC_0184.JPG 879 KB 2256x1496 image/jpeg #186 DSC_0185.JPG 919 KB 2256x1496 image/jpeg

För att överföra bilden från kameran så kan man köra kommandot:
>gphoto2 -p 186 --filename=/home/niclas/Desktop/bild.jpg
OBS, ovanstående exempelkod så är argumentet efter -p den 185:e filen som finns på kameran, vilket är bild DSC_0185.JPG, det är alltså det soms tår efter # som är själva bildid som -p skall ha. Sen är det argumentet till --filename som jag vill kunna specfiera själva när jag köra bash-skriptet.

Jag vore jättetacksam om någon hade lust att hjälpa mig.

MVH Niclas

Visa signatur

Har bytt namn från: nulleman ~ Blogg: http://skorpion.se
MacBook Pro: 15.4' ~ 1.83GHz ~ 1512MB RAM ~ 80GB HDD
Medlem i signaturen blodtörstiga Appleanvändare

Permalänk

Har du försökt själv? Om inte, gör detta först och berätta vad du kör fast på.

Permalänk
Medlem

Nåt sånt här borde funka, inte testat dock.

#!/bin/bash if [ "x$1" == "x" ] then defpath="~/Bilder" else defpath=$1 fi gphoto2 --capture-image imgnum=`gphoto2 -L | tail -1 | awk -F' ' '{print $1}' | sed 's/#//'` gphoto2 -p $imgnum --filename "$defpath/'bild-%n'.jpg"

EDIT: härmar zypher_X med sed

Visa signatur

Hur man installerar program i *nix | There is no Swedish conspiracy

these days you can't use the Web at 2400 baud because the ads are 24KB - Bill Joy

Permalänk
Medlem

Snabbt skrivet och utan att kunna testa:

#!/bin/bash #vart gphoto2 ligger gphoto2=$(which gphoto2) #vart bilden sparas som inget argument anges default_folder="~/" #ta en bild $gphoto --capture-image #Vad har bilden för nummer? #(ta sista raden från gphoto -L, första kolumnen och ta bort #) number=$(tail -n1 $gphoto -L | awk '{print $1}' | sed 's/#//') #om användaren inte skickar med en path... if [ -z "$1"] then file="$default_folder$number.jpg" else file="$1" fi #hämta bilden $gphoto2 -p $number --filename:$file

[I]Edit: attans... aldrig för man vara först...
Måste lära mig att uppdatera tråden innan jag svarar.

Visa signatur

Stolt användare av en ibook 300 MHz (dasslocket)

Permalänk
Medlem

zypher_X: gphoto2=`which gphoto2` är ju rätt smidigt annars

Visa signatur

Hur man installerar program i *nix | There is no Swedish conspiracy

these days you can't use the Web at 2400 baud because the ads are 24KB - Bill Joy

Permalänk
Medlem

Ah tack! Ändrar.

Anledningen att jag har den raden med är att om man vill köra scriptet från ett cron-jobb eller liknande så finns inte alla program i dess $PATH.

Visa signatur

Stolt användare av en ibook 300 MHz (dasslocket)

Permalänk

Om man vill ha ut siffran behöver man inte använda både awk och sed, man klarar sig fint med sed

sed 's/#\([0-9]\{1,\}\).*/\1/g'

Permalänk
Medlem

Ah, sed är grymt, men ack så krångligt =/

Visa signatur

Hur man installerar program i *nix | There is no Swedish conspiracy

these days you can't use the Web at 2400 baud because the ads are 24KB - Bill Joy

Permalänk
Medlem

Tack grabbar, blev lite ändringar i koden, såhär blev slutresultatet:

#!/bin/bash #vart gphoto ligger gphoto2=$(which gphoto2) #vart bilden skall sparas om inget argument anges default_folder="$HOME/" #ta en bild $gphoto2 --capture-image #vad har bilden för nummer? #(ta sista raden från gphoto2 -L, första kolumnen och ta bort #) number=`$gphoto2 -L | tail -1 | sed 's/#\([0-9]\{1,\}\).*/\1/g'` #om användaren inte skickar med en path if [ -z "$1" ] then file="$default_folder$number.jpg" else file="$1/$number.jpg" fi #hämta bilden $gphoto2 -p $number --filename=$file

Av någon anledning så funkade det inte att spcifiera ~/ som katalog. oavsett om jag gjorde det när jag själv kör kommandot eller via skriptet. Däremot funkar $HOME bra

Razor-SWE: Jepp, men jag kan i princip bara sätta variabler från text och användar-indata (det som är $1 $2 osv)
Eftersom att jag inte direkt kunde läsa raden som jag ville ha så blev det att köra:
>gphoto2 -L > /tmp/takeimg.tmp
sedan
>tail -1 /tmp/takeimg.tmp
Sen kom jag inge längre. Jag hittade inget exempel på nätet (måste ha letat dåligt, men sökte i en halvtimme) som läste in filen som jag behövde, sen hade det varit det sista som jag inte kunde heller, att läsa bildnumret, dvs #195 från raden

Tack än en gång

EDIT: nu när ni hjälpt mig såhär långt att jag har det som behövs för att plocka ut den data som behövs så ska jag nog kunna fortsätta själv på skriptet. En sak som inte är fullt korrekt är filändelsen på filen som man sparar. Ibland så är det en .NEF som är Nikons RAW-filformat. Istället för image/jpeg så står det något annat vid gphoto -L. Beroende på det så bör jag nu kunna sätta filändelsen i förhållande till det. Önska mig lycka till

MVH Niclas

Visa signatur

Har bytt namn från: nulleman ~ Blogg: http://skorpion.se
MacBook Pro: 15.4' ~ 1.83GHz ~ 1512MB RAM ~ 80GB HDD
Medlem i signaturen blodtörstiga Appleanvändare

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Lunke
zypher_X: gphoto2=`which gphoto2` är ju rätt smidigt annars

Varför inte bara skriva 'gphoto2' då? which funkar ju bara om det finns i PATH, och gör det det så behöver man ju ingen absolut sökväg...

Permalänk

nillon:

Helt rätt! Pluspoäng för den observationen

Permalänk
Medlem

Bahh, jag får inte till något regulärt uttryck för att hämta image/jpeg
Får lov att fråga vad några saker betyder:
strängen: #167 DSC_0166.JPG 899 KB 2256x1496 image/jpeg
Regexp:
sed 's/#\([0-9]\{1,\}\).*/\1/g'
Det kommer skriva ut 167

Vad betyder/tolkar jag rätt?
1. s/
2. # Det lär väl vara att den skall hitta tecknet #
3. \ escapetecken?
4. ( början på en match
5. [0-9]\{1,\} matchar 0-9 och minimum 1 tecken till oändligt antal teckan
6. \) escapetecken och slutet på en match
7. */ vad är detta
8. \1 är det detta som är det som plockas ut? Alltså 167
9. /g något slags slut på regexpen?

Visa signatur

Har bytt namn från: nulleman ~ Blogg: http://skorpion.se
MacBook Pro: 15.4' ~ 1.83GHz ~ 1512MB RAM ~ 80GB HDD
Medlem i signaturen blodtörstiga Appleanvändare

Permalänk

skorpion:

1. början på ett substitute-kommando i sed, dvs om s/a/b/ betyder det matcha a och byt ut mot b.
2. rätt
3. rätt
4. nja, allt mellan de första två /-tecknen är en match. (..) innebär att det som är innanför ska sparas i en variabel, men själva paranteserna måste man ha \ innan.
5. rätt
6. se ovan
7. en punkt innebär matchning av godtyckligt tecken, och stjärnan innebär matcha noll eller fler av föregående, dvs noll eller fler godtyckliga tecken. I detta fallet är det viktigt att vi matchar hela raden (varför?)
8. rätt
9. här får jag nog rätta mitt eget exempel, /g behövs inte i detta fallet. /g gör att matchningen upprepas flera gånger på raden (om möjligt), men i detta fallet vet vi att den bara ska matcha en gång per rad. Själva g-et kan man alltså ta bort.

Om man är pedantisk ser alltså en bättre variant ut såhär:

sed 's/^#\([0-9]\{1,\}\).*$/\1/'

Permalänk
Medlem

Nu ska vi se här om jag klarar av att plocka ut det jag vill ha
Enligt http://se2.php.net/manual/en/reference.pcre.pattern.syntax.ph... så ska \s matcha blanksteg, går det att använda samma i detta fall?

strängen: #167 DSC_0166.JPG 899 KB 2256x1496 image/jpeg
Försäker att plocka ut image/jpeg
Regexp:
s/.*\s\([a-z\/]\{1,\}\)/\1/

Tjohooo, jag klarade det

Men om vi säger såhär. Jag vill att varje del av strängen skall bli olika variabler, typ $var0=167 $var1=DSC_0166.JPG osv, hur gör man det? Här ovan säger man ju att det som innan ( och ) ska vara \1? Går det att göra fler ( ) och göra det till en \2?

Visa signatur

Har bytt namn från: nulleman ~ Blogg: http://skorpion.se
MacBook Pro: 15.4' ~ 1.83GHz ~ 1512MB RAM ~ 80GB HDD
Medlem i signaturen blodtörstiga Appleanvändare

Permalänk

Japp, om man har flera parenteser i regexpet så blir det som matchas i den första \1, andra \2 osv.

Jag skulle också rekommendera att inte titta för mycket i php-manualen.. php använder en annan regexp-motor, och det är inte allt som går att flytta över direkt till sed. Som exempel hade man i php kunnat köra med [0-9]+, istället för {1,}-konstruktionen, men "+" finns ej i sed.

Permalänk
Medlem

Ang om att jag tittar i php-manualen så är det php som är språket som jag kan bäst, därför är jag van vid den syntaxen mest och dess funktioner. Har varit lite knepiogt att försöka översäta en del funktioner och syntaxer till bash, men tillslut gick det

Men om flera paranteser används och det blir \1 och \2 hur skall jag tillämpa det i sed? Blir båda utskrivna efter varandra då? Så kan jag inte ha. Eller kan man komma åt dem utanför sed's regexp? Så att \1 tex kan kommas åt via $var1 och \2 är $var2?

Nu har jag iaf vidareutvecklat skriptet en del. Såhär ser det ut nu.

#!/bin/bash #information om skriptet echo "Usage: takeimg [directory] [exec] " echo " directory: ... If not specified, $HOME will be used" echo " exec: If not specified, it will not try to open the file" echo " gimp kview showfoto showimg gwenview pornview quickshow " echo "Created by Niclas Gustafsson, 2005-11-19, with help by: Lunke, zypher_x and Razor-SWE at forum.sweclockers.com, Thanks! " #om help eller h är ett argument, dö efter att informationen om skriptet skrivits ut. if [ "$1" == "help" -o "$1" == "h" ] then exit fi #vart gphoto ligger gphoto2=$(which gphoto2) #vart bilden skall sparas om inget argument anges default_folder="$HOME/" #ta en bild $gphoto2 --capture-image #vad har bilden för nummer? #(ta sista raden från gphoto2 -L, första kolumnen och ta bort #) number=`$gphoto2 -L | tail -1 | sed 's/#\([0-9]\{1,\}\).*/\1/g'` #hämta bildtypen så att filen får rätt filändelse if [ `$gphoto2 -L | tail -1 | sed 's/.*\s\([a-z\/]\{1,\}\)/\1/'` == "image/jpeg" ] then type=".jpg" else type=".nef" fi #om användaren inte skickar med en path if [ -z "$1" ] then file="$default_folder$number$type" else file="$1/$number$type" fi #hämta bilden $gphoto2 -p $number --filename=$file #om användaren specifierar ett program att öppna filen med... if [ `which $2` ] then #...öppna då filen med något av dessa program case $2 in gimp ) gimp $file;; kview ) kview $file;; showfoto ) showfoto $file;; showimg ) showimg $file;; gwenview ) gwenview $file;; pornview ) pornview $file;; quickshow ) quickshow $file;; esac fi

Visa signatur

Har bytt namn från: nulleman ~ Blogg: http://skorpion.se
MacBook Pro: 15.4' ~ 1.83GHz ~ 1512MB RAM ~ 80GB HDD
Medlem i signaturen blodtörstiga Appleanvändare

Permalänk

Några grejer:

gphoto2=$(which gphoto2)

Den raden är som sagts ovan helt meningslös.

sed 's/#([0-9]{1,}).*/1/g'

Har du inte glömt ett backslash här? dvs \1. Samma sak i nästa sed-kommando. Dessutom måste man escape:a {1,} till \{1,\} i sed.

Angående bash-programmering är ett tips att titta här för en guide:

http://www.tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html

Anledningen till att inte läsa för mycket på php-sidan är alltså inte pga språket i sig, utan för att det finns skillnader i hur regexp tolkas mellan php och sed. Lite förenklat kan man säga att sed's regexp-motor inte har alla funktioner som pcre-motorn, som används i php.

Sedan förstår jag nog inte riktigt vad du menar med att matcharna skulle skrivas ut efter varandra? Det är ju helt upp till en själv att bestämma. T ex:

sed 's/(...)(...)/Detta är andra matchningen: \2, och första är \1/'

Permalänk
Medlem

Det var php-taggarna som tog bort \ framför 1

Om säger att jag har strängen "Jag heter Niclas"
Och jag vill dela upp den strängen i 3 variabler som jag kan använda på 3 olika ställen, hur gör jag då?
Dvs så att tex $1=Jag, $2=heter, $3=niclas
Så som jag förstod sed så var att det man hämtar ut skrivs ut på samma rad som sed-kommandot. Jag vill inte att det skall skrivas ut alls utan bara sparas i en variabel om det går.

/Niclas

Visa signatur

Har bytt namn från: nulleman ~ Blogg: http://skorpion.se
MacBook Pro: 15.4' ~ 1.83GHz ~ 1512MB RAM ~ 80GB HDD
Medlem i signaturen blodtörstiga Appleanvändare

Permalänk

Ok, nu förstår jag vad du menar. Sed arbetar med rader (egentligen strömmar, men strunt samma), och har inget enkelt sätt att tilldela variabler utanför programmet. Det du vill göra är att tilldela variabler eller arrayer i bash-scriptet.. vilket inte är lika enkelt. Ett tips är kanske att använda perl istället.

Permalänk
Medlem

Okej, får titta lite på perl imn, nu ska jag sova tror jag
Tack för idag
Gonatt

/Niclas

Visa signatur

Har bytt namn från: nulleman ~ Blogg: http://skorpion.se
MacBook Pro: 15.4' ~ 1.83GHz ~ 1512MB RAM ~ 80GB HDD
Medlem i signaturen blodtörstiga Appleanvändare

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Razor-SWE
Som exempel hade man i php kunnat köra med [0-9]+, istället för {1,}-konstruktionen, men "+" finns ej i sed.

[0-9]\+ fungerar i sed.

Citat:

tail -1 | sed 's/#\([0-9]\{1,\}\).*/\1/g'

Och varför överhuvudtaget blanda in tail när man klarar sig fint med enbart sed?

sed -n '$s/#\([0-9]\+\).*/\1/p'

Permalänk
Citat:

Ursprungligen inskrivet av lefant
[0-9]\+ fungerar i sed.

Det var intressant (och korrekt). Då står det fel i boken "sed & awk" av Robbins.

skorpion:

Angående att läsa in ord i variabler, exempelvis funkar följande:

echo "ett två" | while read a b do echo $a echo $b done

ger resultatet:
ett
två

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Razor-SWE
Det var intressant (och korrekt). Då står det fel i boken "sed & awk" av Robbins.

Du kan till och med få [0-9]+ att fungera (flagga -r till sed).
Då slipper du även escapa t.ex. paranteser.

sed -r 's/#([0-9]+).*/\1/'

Citat:

Angående att läsa in ord i variabler, exempelvis funkar följande:

[code]echo "ett två" | while read a b
do
echo $a
echo $b
done

[/code]

Man kan också göra så här...

foo=(ett två) echo ${foo[0]} echo ${foo[1]}

Permalänk
Medlem

cat <<EOF USAGE: `basename $0` [directory] [exec] directory: ... If not specified, $HOME will be used" exec: If not specified, it will not try to open the file" gimp kview showfoto showimg gwenview pornview quickshow Created by Niclas Gustafsson, 2005-11-19, with help by: Lunke, zypher_x and Razor-SWE at forum.sweclockers.com, Thanks! EOF

Bättre än en massa echo-satser i scriptet.

#vart bilden skall sparas om inget argument anges default_folder="$1" default_folder=${default_folder:-"$HOME}

Spara in ett if-else block. Kortare script...

Visa signatur

I am not a politician and my other habits are also good.

Permalänk
Citat:

Ursprungligen inskrivet av lefant
Du kan till och med få [0-9]+ att fungera (flagga -r till sed).
Då slipper du även escapa t.ex. paranteser.

sed -r 's/#([0-9]+).*/\1/'

Ja, fast detta tycks vara begränsat till gnu sed. BSDs sed känner inte igen "-r" t ex.

Permalänk
Medlem

Sen tycker jag personligen att det är ett oskick att köra scripts via bash, jag ser alltid till att skriva dom för sh..

Sen att sh är bash i just *LINUX* spelar ingen roll, jag scriptar för många OS..

Visa signatur

AmigaOS <> IRIX <> Solaris <> Linux <> HP-UX <> OpenBSD

Jag kör min 2.4Ghz speldata i 3.67Ghz. Min riktiga dator kör 68060-60 i 50Mhz.