/ 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
for-in-do med jokertegn?
Fra : Thomas Jensen


Dato : 02-09-10 11:45

Hvis man bruger jokertegn i følgende kommando

for M in *.mpeg; do echo "$M"; done

fungerer det efter hensigten, så længe der er .mpeg-filer i mappen. Hvis
der ikke er, så sendes tekststrengen "*.mpeg" til M.

NÃ¥r nu for-kommandoen ved at parameteren *.mpeg refererer til filnavne,
hvorfor opfatter den det så som en tekststreng? Burde der ikke returneres
null til M, eller noget i den stil, når der ikke er nogen .mpeg-filer,
sådan at do-done delen springes over?

Man behøver faktisk ikke give noget input til for-kommandoen -

for M in ;do echo "hallo"; done

virker fint, og der echo "hallo" udføres ikke. Derfor kunne en løsning
måske være

ls -Q *.mpeg > ls.txt
for M in `cat ls.txt`; do echo "$M"; done

men de quotes som -Q sætter om filnavnene, bliver ikke "opfattet" -
resultater er fx

"The
Queen
-
DR2(DR)
-
ons
01
sep
2010
20_36_00.mpeg"

Der bliver sat quotes om filnavnet, men alligevel opfattes det som en
serie parametre. Underligt? Jeg har også prøvet med

ls --quoting-style=shell *.mpeg > ls.txt

m.m., men resultatet er det samme.


Lige nu er min løsning at bruge

for M in *.mpeg; do echo "$M"; done

og så efterfølgende teste om M er en fil (eller bare tekststrengen
"*.mpeg"). Det virker, men jeg synes det er lidt uelegant.

Er der nogen der kan foreslå en anden løsning?

--
Thomas Jensen

 
 
Klaus Ellegaard (02-09-2010)
Kommentar
Fra : Klaus Ellegaard


Dato : 02-09-10 12:07

Thomas Jensen <lianergoist@tj-software.dk> writes:

>Når nu for-kommandoen ved at parameteren *.mpeg refererer til filnavne,
>hvorfor opfatter den det så som en tekststreng?

Det ved den ikke. Det er shell'en, der laver den "expansion", og
hvis der ikke findes matches, konkluderer shell'en, at du bare
mente tekststrengen "*.mpeg" og ikke et wildcard. "for" aner ikke,
hvordan shell'en kom frem til den ene eller den anden konklusion.

>ls -Q *.mpeg > ls.txt
>for M in `cat ls.txt`; do echo "$M"; done

Prøv...

ls -Q *.mpeg |
while read M
do
   echo $M
done

Så skulle du gerne få det ønskede, da "read" læser en hel linje
ad gangen.

Mvh.
   Klaus.

Tom G. Christensen (02-09-2010)
Kommentar
Fra : Tom G. Christensen


Dato : 02-09-10 12:19

Thomas Jensen wrote:
> Hvis man bruger jokertegn i følgende kommando
>
> for M in *.mpeg; do echo "$M"; done
>
> fungerer det efter hensigten, så længe der er .mpeg-filer i mappen. Hvis
> der ikke er, så sendes tekststrengen "*.mpeg" til M.
>
> NÃ¥r nu for-kommandoen ved at parameteren *.mpeg refererer til filnavne,
> hvorfor opfatter den det så som en tekststreng? Burde der ikke returneres
> null til M, eller noget i den stil, når der ikke er nogen .mpeg-filer,
> sådan at do-done delen springes over?

I en bourne shell kan du sætte nullglob for at opnå det du ønsker.

$ for x in *.INGEN; do echo $x; done
*.INGEN
$ shopt -s nullglob
$ for x in *.INGEN; do echo $x; done
$

> ls -Q *.mpeg > ls.txt
> for M in `cat ls.txt`; do echo "$M"; done
>
> men de quotes som -Q sætter om filnavnene, bliver ikke "opfattet" -
> resultater er fx
>
> "The
> Queen
> -
> DR2(DR)
> -
> ons
> 01
> sep
> 2010
> 20_36_00.mpeg"
>
> Der bliver sat quotes om filnavnet, men alligevel opfattes det som en
> serie parametre. Underligt? Jeg har også prøvet med
>
> ls --quoting-style=shell *.mpeg > ls.txt
>
> m.m., men resultatet er det samme.
>
Du kan nulstille IFS, så skilles der ikke ved mellemrum.

$ ls
endnu en fil med mellemrum.mpeg fil med mellemrum.mpeg
$ for M in $(ls *.mpeg 2>/dev/null); do echo "$M"; done
endnu
en
fil
med
mellemrum.mpeg
fil
med
mellemrum.mpeg
$ OIFS=$IFS
$ IFS=""
$ for M in $(ls *.mpeg 2>/dev/null); do echo "$M"; done
endnu en fil med mellemrum.mpeg
fil med mellemrum.mpeg
$ IFS=$OIFS

-tgc

Thomas Jensen (02-09-2010)
Kommentar
Fra : Thomas Jensen


Dato : 02-09-10 13:09

On Thu, 02 Sep 2010 11:07:07 +0000, Klaus Ellegaard wrote:

> Prøv...
>
> ls -Q *.mpeg |
> while read M
> do
>    echo $M
> done
>
> Så skulle du gerne få det ønskede, da "read" læser en hel linje ad
> gangen.


Jep, det virker efter hensigten. Man kan måske med fordel tilføje "2>/dev/
null" til ls-kommandoen, da der ellers kommer en advarsel på skærmen,
hvis der ingen .mpeg-filer findes. Ikke fordi det har nogen praktisk
betydning, men det ser så dumt ud med "ls: kan ikke tilgå "*.mpeg": No
such file or directory". Hvis nogen så det, kunne de jo tro man havde
lavet en fejl...


--
Thomas Jensen

Thomas Jensen (04-09-2010)
Kommentar
Fra : Thomas Jensen


Dato : 04-09-10 13:31

On Thu, 02 Sep 2010 13:18:33 +0200, Tom G. Christensen wrote:

Tom,

Jeg beklager, at jeg ikke har reageret på dit rigtig gode svar før nu.

> I en bourne shell kan du sætte nullglob for at opnå det du ønsker.
>

Super! Jeg undrede mig lidt over kommandoen "shopt" - "man shopt" gav
ingenting... men så slog det mig, at prøve med "man bash" - og sikke da
en guldgrubbe af information! Jeg har et par bøger om Linux, men der er
ikke rigtig nogen der kommer ned under overfladen på det med shell og
scripts - men nu ved jeg da hvor jeg skal kigge...


> Du kan nulstille IFS, så skilles der ikke ved mellemrum.
>

Og igen, IFS står sgu' ikke i indexet på nogen af de bøger jeg har. Men
jeg er da blevet lidt klogere nu - selvom jeg ikke helt hvorstår hvad man
skal bruge det til.

"*   Expands to the positional parameters, starting from one. When
   the expansion occurs within double quotes, it expands to a sin‐
   gle word with the value of each parameter separated by the first
   character of the IFS special variable. That is, "$*" is equiva‐
   lent to "$1c$2c...", where c is the first character of the value
   of the IFS variable. If IFS is unset, the parameters are sepa‐
   without intervening separators."

Hvornår har man brug for "expansion [...] within double quotes"? Man
bruger vel (double) quotes fordi man vil have det opfattet som én enhed?


--
Thomas Jensen

Klaus Alexander Seis~ (04-09-2010)
Kommentar
Fra : Klaus Alexander Seis~


Dato : 04-09-10 15:10

Thomas Jensen skrev:

> Hvornår har man brug for "expansion [...] within double quotes"?
> Man bruger vel (double) quotes fordi man vil have det opfattet
> som én enhed?

Hvis vi leger at et script tager 3 argumenter (${1}, ${2} og ${3}),
vil "${*}" være lig "${1} ${2} ${3}" hvis det første tegn i ${IFS}
er et mellemrum. Hvis der ikke er gåseøjne omkring ${*} opfattes
udtrykket (i det konkrete tilfælde med tre argumenter) som minimum
tre separate “ord”.

Mvh,

--
Klaus Alexander Seistrup
http://klaus.seistrup.dk/

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

Månedens bedste
Årets bedste
Sidste års bedste