/ Forside / Teknologi / Operativsystemer / Linux / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
Linux
#NavnPoint
o.v.n. 11177
peque 7911
dk 4814
e.c 2359
Uranus 1334
emesen 1334
stone47 1307
linuxrules 1214
Octon 1100
10  BjarneD 875
mellemrum og escapes i bash-variabler
Fra : Niels Andersen


Dato : 10-11-01 10:38

Jeg sidder og bakser med et bash-script, som ikke vil helt som jeg vil,
når der er mellemrum i filnavnene.

Lad os sige, at der rent faktisk er en fil, der hedder "filnavn med
mellemrum".

TEST="filnavn\ med\ mellemrum"
echo less $TEST
less $TEST

Giver:
less filnavn\ med\ mellemrum
filnavn\: Ingen sådan fil eller filkatalog
med\: Ingen sådan fil eller filkatalog
mellemrum: Ingen sådan fil eller filkatalog

Hvis jeg tager den første linje, og skrive den direkte i prompten, så
virker det fint. Men hvordan får jeg det til at virke i denne
sammenhæng, i et bash-script?

Det skal bruges til noget backup-værk, noget i stil med:
$DATA = "\
/sti til filer/ \
/sti til andre filer/ \
"
og det er så blandt parametrene til tar. Men det giver ovenstående
problem. Og nej, jeg kan ikke bare droppe mellemrum i filnavnene. :)

--
Mvh.

Niels Andersen



 
 
Klaus Alexander Seis~ (10-11-2001)
Kommentar
Fra : Klaus Alexander Seis~


Dato : 10-11-01 10:42

Niels Andersen skrev:

> less $TEST

Prøv med 'less "$TEST"'.


// Klaus

--
><>°    vandag, môre, altyd saam

Niels Andersen (10-11-2001)
Kommentar
Fra : Niels Andersen


Dato : 10-11-01 11:13

> > less $TEST
> Prøv med 'less "$TEST"'.

Hvis jeg fjerner double-quotes omkring selve filnavnet, så virker det.
Men der skal angives et antal filer, og så går der ged i det...

Jeg prøver lige igen:

TEST="\
filnavn\ med\ mellemrum \
andenfil\ med\ mellemrum \
"
echo less $TEST
less $TEST

giver:

less filnavn\ med\ mellemrum andenfil\ med\ mellemrum
filnavn\: Ingen sådan fil eller filkatalog
med\: Ingen sådan fil eller filkatalog
mellemrum: Ingen sådan fil eller filkatalog
andenfil\: Ingen sådan fil eller filkatalog

Altså, den første linje vise, at alt tilsyneladende er godt, men det
virker altså ikke.

Og hvis jeg her skriver 'less "$TEST"', så tror den at det er ét langt
filnavn.

--
Mvh.

Niels Andersen



Klaus Alexander Seis~ (10-11-2001)
Kommentar
Fra : Klaus Alexander Seis~


Dato : 10-11-01 12:11

Niels Andersen skrev:

> Jeg prøver lige igen:
>
> TEST="\
> filnavn\ med\ mellemrum \
> andenfil\ med\ mellemrum \
> "
> echo less $TEST
> less $TEST

Så skift din IFS ud med noget andet, fx

#v+
OLDIFS="${IFS}"
IFS='
'

TEST='
filnavn med mellemrum
andenfil med mellemrum
'

for FIL in ${TEST}
do
echo ${FIL}
done

IFS="${OLDIFS}"
#v-


// Klaus

--
><>°    vandag, môre, altyd saam

Claus Rasmussen (10-11-2001)
Kommentar
Fra : Claus Rasmussen


Dato : 10-11-01 11:40

Niels Andersen wrote:

> Jeg sidder og bakser med et bash-script, som ikke vil helt som jeg vil,
> når der er mellemrum i filnavnene.

sh, som bash bygger på, blev lavet dengang, da mellemrum ikke var tilladt
i filnavne. Man har så klampret noget på, der kan håndtere det - for det
meste

Men generelt virker det ikke særligt godt og er urimeligt kompliceret -
læs f.eks afsnittet om quoting i man bash.


> Lad os sige, at der rent faktisk er en fil, der hedder "filnavn med
> mellemrum".
>
> TEST="filnavn\ med\ mellemrum"
> echo less $TEST
> less $TEST

Generelt skal du _altid_ putte dine variable i citationstegn. Altså
skrive

less "$TEST"

Det gælder ikke bare mht filnavne men også hvis dine variable rummer
options o.lign. De fleste gange går det godt, men så snart der kommer
en blank (eller en tom streng) skal du have citationstegn på.

Almindelig dovenskab plus en konvention om, at man /som regel/ ikke
har blanke i filnavne, gør at du for det meste kan slippe godt fra
ikke at have citationstegn omkring ekspansioner af variable.


Når dit problem er, at du vil have variablen til at rumme flere filnavne
er det game-over - det kan bash simpelthen ikke klare med almindelige
variable. Ikke i alle situationer i hvert fald.

I stedet kan du bruge arrays:

navne=(Hej\ med\ dig du\ gamle)

for navn in "${navne}"
do echo $navn
done

Det virker, men det er en noget tung syntax...

-Claus



Claus Rasmussen (10-11-2001)
Kommentar
Fra : Claus Rasmussen


Dato : 10-11-01 11:50

Jeg jokkede i min egen spinat:

[...]

> Generelt skal du _altid_ putte dine variable i citationstegn. .....

Rigtigt.

[...]

> do echo $navn
^^^^^

Ups, jeg mente:

do echo "$navn"

MVH

-Claus



Klaus Alexander Seis~ (10-11-2001)
Kommentar
Fra : Klaus Alexander Seis~


Dato : 10-11-01 12:04

Claus Rasmussen skrev:

> Generelt skal du _altid_ putte dine variable i citationstegn.
> Altså skrive
>
> less "$TEST"

Det er osse en god vane at putte krøllebøller rundt om variabel-
navnet: "${TEST}".


// Klaus

--
><>°    vandag, môre, altyd saam

Niels Andersen (10-11-2001)
Kommentar
Fra : Niels Andersen


Dato : 10-11-01 12:44

"Claus Rasmussen" <clr@cc-consult.dk> wrote in message
news:3bed0435$0$4931$ba624c82@nntp02.dk.telia.net...
> Generelt skal du _altid_ putte dine variable i citationstegn. Altså
> skrive
>
> less "$TEST"

Det lyder som en god ide.

> Når dit problem er, at du vil have variablen til at rumme flere
filnavne
> er det game-over - det kan bash simpelthen ikke klare med almindelige
> variable. Ikke i alle situationer i hvert fald.

Dang. Jamenhvadgørmanså?

Mit problem skal åbenbart løses på en helt anden måde, så nu får i altså
hele scriptet.
Det er en simpel backup-ting:

#!/bin/bash
TARGET=/backup/backup-`date '+%Y-%m-%d'`
SOURCE="\
/home/niels/noget med mellemrum \
--exclude /home/niels/noget med mellemrum/noget ligegyldigt der fylder
meget \
/usr/local/noget andet her \
"
tar cvf $TARGET.tar "$SOURCE"

> I stedet kan du bruge arrays:
>
> navne=(Hej\ med\ dig du\ gamle)
>
> for navn in "${navne}"
> do echo $navn
> done

Og så er det, at jeg ikke kan få det til at passe ind, i min aktuelle
problemstilling.
Hvis jeg kalder tar flere gange, med samme tarball som target, så skulle
det vel virke. Tror jeg. Ved ikke om det vil virke hvis jeg også zipper,
men det ved jeg heller ikke om jeg vil gøre.
Men så er der lige "--exclude"-tingen. Der går jeg i stå.

--
Mvh.

Niels Andersen



Kent Friis (10-11-2001)
Kommentar
Fra : Kent Friis


Dato : 10-11-01 13:18

Den Sat, 10 Nov 2001 12:43:46 +0100 skrev Niels Andersen:
>"Claus Rasmussen" <clr@cc-consult.dk> wrote in message
>news:3bed0435$0$4931$ba624c82@nntp02.dk.telia.net...
>> Generelt skal du _altid_ putte dine variable i citationstegn. Altså
>> skrive
>>
>> less "$TEST"
>
>Det lyder som en god ide.
>
>> Når dit problem er, at du vil have variablen til at rumme flere
>filnavne
>> er det game-over - det kan bash simpelthen ikke klare med almindelige
>> variable. Ikke i alle situationer i hvert fald.
>
>Dang. Jamenhvadgørmanså?
>
>Mit problem skal åbenbart løses på en helt anden måde, så nu får i altså
>hele scriptet.
>Det er en simpel backup-ting:
>
>#!/bin/bash
>TARGET=/backup/backup-`date '+%Y-%m-%d'`
>SOURCE="\
>/home/niels/noget med mellemrum \
>--exclude /home/niels/noget med mellemrum/noget ligegyldigt der fylder
>meget \
>/usr/local/noget andet her \
>"
>tar cvf $TARGET.tar "$SOURCE"

Flytter filnavnene ned i stedet for $SOURCE

eller du kan bruge set:

set -- "/home/bla" "/home/bla bla" "noget mere"
tar cvs $TARGET.tar "$@"

Mvh
Kent
--
Det skete i de dage i november engang
at de første kataloger satte hyggen igang

Claus Rasmussen (10-11-2001)
Kommentar
Fra : Claus Rasmussen


Dato : 10-11-01 13:25

Niels Andersen wrote:

> Dang. Jamenhvadgørmanså?

Sådan her:

TARGET=/backup/backup-$(date '+%Y-%m-%d').tar.gz

SOURCE=(
--exclude "en fil som vi ikke vil have med"
--exclude "en anden fil der heller ikke skal med"
"fil med blanke som skal med"
"en anden fil med blanke som også skal med"
)

tar zcvf "$TARGET" "${SOURCE}"

Læg mærke til:

o At arrayet har seks elementer. --exclude optionen er et selv-
stændigt argument. Den står bare på samme linie som filnavnet
for at gøre det mere gennemskueligt, hvad der foregår.
o At der ikke skal bruges backslash som linieseparator, når man
definerer et array.
o At du heller ikke behøves backslash til at escape mellemrum -
du kan nøjes med at putte hele filnavnet i citationstegn.
o At du sikkert skal have --exclude optionerne først.
o At det er lettere at læse, hvis du bruger $() i stedet for
backticks (`)
o At jeg lige putter en 'z' option på tar, så resultatet bliver
komprimeret automatisk.

Har du lyst, kan du lege lidt med arrays i din shell. Prøv f.eks flg.:

v=(hej med dig)
echo ${#v}
echo $v
echo ${v[0]}
echo ${v[1]}
echo ${v[2]}
for i in "${v}"; do echo $i; done
for i in "${v[*]}"; do echo $i; done
for (( i = 0; i < ${#v}; ++i )); do echo "${v[i]}"; done

MVH
-Claus



Kim Petersen (10-11-2001)
Kommentar
Fra : Kim Petersen


Dato : 10-11-01 17:19

"Niels Andersen" <niels-usenet@myplace.dk> writes:
> Jeg sidder og bakser med et bash-script, som ikke vil helt som jeg vil,
> når der er mellemrum i filnavnene.
> Det skal bruges til noget backup-værk, noget i stil med:
> $DATA = "\
> /sti til filer/ \
> /sti til andre filer/ \
> "
> og det er så blandt parametrene til tar. Men det giver ovenstående
> problem. Og nej, jeg kan ikke bare droppe mellemrum i filnavnene. :)

Løser dette dit problem?

tar cvfT tarball.tar - <<%%STOP%%
/sti til filer/
/sti til andre filer/
%%STOP%%

>
> --
> Mvh.
>
> Niels Andersen
>
>

--
Mvh. Kim Petersen /| Tlf: +4575831551 |\ Jomfru Ingefreds Vej 18
Software Engineer / | Fax: (none atm.) | \ 7100 Vejle
LSS / | Email: kim@vindinggaard.dk | \ DK - Danmark

Niels Andersen (11-11-2001)
Kommentar
Fra : Niels Andersen


Dato : 11-11-01 22:09

"Kim Petersen" <kim@vindinggaard.dk> wrote in message
news:u1w24n1l.fsf@localhost.localdomain...
> Løser dette dit problem?
>
> tar cvfT tarball.tar - <<%%STOP%%
> /sti til filer/
> /sti til andre filer/
> %%STOP%%

Nope. Og det ser desuden ud til, at den ikke fatter --excludes på den
måde.

Jeg prøver lige at tage problemet fra en helt anden vinkel, i en ny
tråd...

--
Mvh.

Niels Andersen



Søg
Reklame
Statistik
Spørgsmål : 177557
Tips : 31968
Nyheder : 719565
Indlæg : 6408885
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste