Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

(ba)sh - ls et affectation de variables

12 réponses
Avatar
Thomas vO
bonjour,

je cherche =C3=A0 r=C3=A9cup=C3=A9rer le plus r=C3=A9cent fichier dans un r=
=C3=A9pertoire :

###begin bash code
#!/bin/sh

OLD=3D$(ls -t fic* |head -1)
CODE=3D$?
echo $CODE
if [ -s ${OLD} ];
then
echo "ok"
fi
###end bash code

le probl=C3=A8me, c'est quand ls ne renvoie rien (il n'existe aucun
fic*)... le code d'erreur est 0, puisque l'affectation fonctionne,
mais ce que je ne comprends pas, c'est que "[ -s rien ]" vaut Vrai
(m=C3=AAme combat avec "-e")... puisque =C3=A7a m'=C3=A9cho "ok".

si une bonne =C3=A2me peut m'expliquer :
1- pourquoi [ -s rien ] vaut vrai ?
2- comment faire =C3=A9chouer le test si $OLD vaut "rien".

merci beaucoup,

--=20
Thomas vO

10 réponses

1 2
Avatar
JKB
Le 03-12-2008, ? propos de
(ba)sh - ls et affectation de variables,
Thomas vO ?crivait dans fr.comp.os.unix :
bonjour,



Bonjour,

je cherche à récupérer le plus récent fichier dans un répertoire :

###begin bash code
#!/bin/sh

OLD=$(ls -t fic* |head -1)
CODE=$?
echo $CODE
if [ -s ${OLD} ];
then
echo "ok"
fi
###end bash code

le problème, c'est quand ls ne renvoie rien (il n'existe aucun
fic*)... le code d'erreur est 0, puisque l'affectation fonctionne,
mais ce que je ne comprends pas, c'est que "[ -s rien ]" vaut Vrai
(même combat avec "-e")... puisque ça m'écho "ok".

si une bonne âme peut m'expliquer :
1- pourquoi [ -s rien ] vaut vrai ?
2- comment faire échouer le test si $OLD vaut "rien".



test x$OLD = x ?

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Avatar
Nicolas George
Thomas vO wrote in message :
OLD=$(ls -t fic* |head -1)



Scrogneugneu, on ne parse pas la sortie de ls dans un script.
Avatar
Stephane CHAZELAS
2008-12-03, 14:24(+00), Nicolas George:
Thomas vO wrote in message :
OLD=$(ls -t fic* |head -1)



Scrogneugneu, on ne parse pas la sortie de ls dans un script.



En l'occurrence, il n'y a pas vraiment d'autre solution avec les
outils standard.

C'aurait du etre:

old=$(ls -td fic* | head -n 1)

Ou:

old=$(ls -t | grep '^fic' | head -n 1)

Au cas ou il y ait trop de fic*.

La seule limitation de cette solution est au cas ou des noms de
fichiers contiennent des sauts de ligne. Auquel cas ca peut etre
contourné en faisant:

old=$(ls -td ./fic* | awk '
NR > 1 && /// {exit}
{print}'
)

auquel cas la limitation est si le nom de fichier se termine par
des sauts de ligne, auquel cas on peut faire:

old=$(ls -td ./fic* | awk '
NR > 1 && /// {exit}
{print}
END {print "."}'
); old=${old%??}


Avec zsh:

old=(fic*(om[1]))

--
Stéphane
Avatar
Thomas vO
À (at) Wed, 3 Dec 2008 15:05:11 +0000 (UTC),
Stephane CHAZELAS nous disait (told us):
En l'occurrence, il n'y a pas vraiment d'autre solution avec les
outils standard.

C'aurait du etre:

[snip]



merci pour tous ces détails (et merci JKB aussi).

mais je peux pas m'empêcher d'incompréhenser quand [ -s 'rien' ]
renvoie Vrai ; il y a une explication ?

Avec zsh:

old=(fic*(om[1]))



on a pas forcément un shell civilisé sous la main ;)

--
Thomas vO
Avatar
Stephane CHAZELAS
2008-12-03, 16:18(+01), Thomas vO:

À (at) Wed, 3 Dec 2008 15:05:11 +0000 (UTC),
Stephane CHAZELAS nous disait (told us):
En l'occurrence, il n'y a pas vraiment d'autre solution avec les
outils standard.

C'aurait du etre:

[snip]



merci pour tous ces détails (et merci JKB aussi).

mais je peux pas m'empêcher d'incompréhenser quand [ -s 'rien' ]
renvoie Vrai ; il y a une explication ?


[...]

[ -s 'rien' ] renvoie vrai si le fichier qui s'appelle 'rien'
existe et n'est pas vide.

[ -n x ] renvoie vrai car "x" n'est pas un argument vide.

[ -n ] renvoie vrai tout comme [ x ] ou [ -s ] renvoie vrai car
ni "x" ni "-n" ne sont des chaines vides.

[ -n "" ] renvoie faux

[ -n $OLD ] est une anerie. Laisser une variable sans ses quotes
a une signification tres tres speciale pour le shell.

[ -n "$OLD" ] renvoie vrai si $OLD contient quelquechose.

--
Stéphane
Avatar
Alain Montfranc
Nicolas George a écrit
Thomas vO wrote in message :
OLD=$(ls -t fic* |head -1)



Scrogneugneu, on ne parse pas la sortie de ls dans un script.



Tu préferes :

find . -type f -maxdepth 1 -name "fic*" -printf "%%fn" | sort -n |
tail -1 | cut -f2-

En esperant qu'il n'y ait pas de newline dans les nom de fichier oeuf
corse
Avatar
Stephane CHAZELAS
2008-12-03, 18:20(+01), Alain Montfranc:
Nicolas George a écrit
Thomas vO wrote in message :
OLD=$(ls -t fic* |head -1)



Scrogneugneu, on ne parse pas la sortie de ls dans un script.



Tu préferes :

find . -type f -maxdepth 1 -name "fic*" -printf "%%fn" | sort -n |
tail -1 | cut -f2-

En esperant qu'il n'y ait pas de newline dans les nom de fichier oeuf
corse


[...]

%A, c'est pour l'access time, %T pour le modification time. Tant
qu'a utiliser des extensions GNU:

find . -maxdepth 1 -name "fic*" -printf "%%f" |
sort -rzn |
tr 'n' 'n' |
head -n 1 |
cut -f2- |
tr '' 'n'

mais il reste le meme probleme des trailing newlines si on
utilise $(...).

--
Stéphane
Avatar
Alain Montfranc
Stephane CHAZELAS a écrit
2008-12-03, 18:20(+01), Alain Montfranc:
Nicolas George a écrit
Thomas vO wrote in message :
OLD=$(ls -t fic* |head -1)



Scrogneugneu, on ne parse pas la sortie de ls dans un script.



Tu préferes :

find . -type f -maxdepth 1 -name "fic*" -printf "%%fn" | sort -n |
tail -1 | cut -f2-

En esperant qu'il n'y ait pas de newline dans les nom de fichier oeuf
corse


[...]

%A, c'est pour l'access time, %T pour le modification time.



Oui au temps pour moi

Tant
qu'a utiliser des extensions GNU:

find . -maxdepth 1 -name "fic*" -printf "%%f" |
sort -rzn |
tr 'n' 'n' |
head -n 1 |
cut -f2- |
tr '' 'n'



Joli, je garde :-D


mais il reste le meme probleme des trailing newlines si on
utilise $(...).


Avatar
Cyrille Lefevre
Thomas vO a écrit :
bonjour,

je cherche à récupérer le plus récent fichier dans un répertoire :

###begin bash code
#!/bin/sh

OLD=$(ls -t fic* |head -1)
CODE=$?
echo $CODE
if [ -s ${OLD} ];
then
echo "ok"
fi
###end bash code

le problème, c'est quand ls ne renvoie rien (il n'existe aucun
fic*)... le code d'erreur est 0, puisque l'affectation fonctionne,



faux, le cr est celui de la commande soumise et non celui de l'affectatio n.

$ x=$(false)
$ echo $?
1

dans le cas présent, c'est le cr de head qui est retourné et no n celui
de ls puisqu'il s'agit d'un pipe, d'ou zero dans tous les cas...

mais ce que je ne comprends pas, c'est que "[ -s rien ]" vaut Vrai
(même combat avec "-e")... puisque ça m'écho "ok".



# attention à la ligne suivante !
$ rm fic*
$ x=$(ls fic*)
$ echo "$x"
fic*

il y a donc bien qqc

si une bonne âme peut m'expliquer :
1- pourquoi [ -s rien ] vaut vrai ?
2- comment faire échouer le test si $OLD vaut "rien".



$ y="fic*"
$ x=$(echo $y)
$ echo "$x" "$y"
fic* fic*
$ [ "$x" = "$y" ] && ceho rien
rien

dans ton cas, le plus simple est de faire la chose en 2 temps pour
pouvoir récupérer le cr de ls :

x=$(ls -t fic* 2> /dev/null)
if (( $? != 0 )); then
rien
fi
x=$(echo "$x" | head -1)

PS : note bien les " un peu partout ci-dessus... grosso merdo, toujours
mettre des " autour des variables sauf si l'on veux explicitement que le
shell joue son rôle comme dans x=$(echo $y)

Cordialement,

Cyrille Lefevre.
--
mailto:Cyrille.Lefevre-news%
supprimer "%nospam% et ".invalid" pour me repondre.
Avatar
Cyrille Lefevre
Alain Montfranc a écrit :
Nicolas George a écrit
Thomas vO wrote in message :
OLD=$(ls -t fic* |head -1)



Scrogneugneu, on ne parse pas la sortie de ls dans un script.



Tu préferes :

find . -type f -maxdepth 1 -name "fic*" -printf "%%fn" | sort -n
| tail -1 | cut -f2-



merci de préciser que cela n'est pas portable (lire GNU).

Cordialement,

Cyrille Lefevre.
--
mailto:Cyrille.Lefevre-news%
supprimer "%nospam% et ".invalid" pour me repondre.
1 2