Il suffit de passer la pipe sort -ravant forou de la laver ls -r.
David Schwartz
Réponses:
27
Dans bash ou ksh, placez les noms de fichiers dans un tableau et parcourez ce tableau dans l'ordre inverse.
files=(/var/logs/foo*.log)for((i=${#files[@]}-1; i>=0; i--));do
bar "${files[$i]}"done
Le code ci-dessus fonctionne également en zsh si l' ksh_arraysoption est définie (elle est en mode d'émulation ksh). Il existe une méthode plus simple dans zsh, qui consiste à inverser l'ordre des correspondances via un qualificatif glob:
for f in/var/logs/foo*.log(On);do bar $f;done
POSIX n'inclut pas de tableaux, donc si vous voulez être portable, votre seule option pour stocker directement un tableau de chaînes est les paramètres positionnels.
set--/var/logs/foo*.log
i=$#while[ $i -gt 0];doeval"f=\${$i}"
bar "$f"
i=$((i-1))done
Une fois que vous utilisez des paramètres positionnels, vous n'avez plus besoin de vos variables iet f; effectuez simplement une shift, utilisez $1pour votre appel baret testez [ -z $1 ]votre while.
user1404316
@ user1404316 Ce serait une manière trop compliquée d'itérer sur les éléments dans l'ordre croissant . Également faux: ni les tests utiles [ -z $1 ]ni [ -z "$1" ]les tests (que faire si le paramètre était *, ou une chaîne vide?). Et en tout cas, cela n'aide pas ici: la question est de savoir comment boucler dans l'ordre inverse.
Gilles 'SO- arrête d'être méchant'
La question indique spécifiquement qu'il itère sur les noms de fichiers dans / var / log, il est donc sûr de supposer qu'aucun des paramètres ne serait "*" ou vide. Je suis cependant corrigé sur le point de l'ordre inverse.
user1404316
7
Essayez ceci, sauf si vous considérez les sauts de ligne comme des "personnages géniaux":
ls /var/logs/foo*.log | tac |while read f;do
bar "$f"done
Existe-t-il une méthode qui fonctionne avec les sauts de ligne? (Je sais que c'est rare, mais au moins pour le plaisir d'apprendre, j'aimerais savoir s'il est possible d'écrire le code correct.)
Mehrdad
Créatif pour utiliser tac pour inverser le flux, et si vous souhaitez vous débarrasser de certains caractères indésirables comme les sauts de ligne, vous pouvez diriger vers tr -d '\ n'.
La réponse la plus votée a brisé la variable fdans ma situation. Cette réponse, cependant, agit à peu près comme un remplacement sans rendez-vous pour la forligne ordinaire .
Serge Stroobandt
2
Si quelqu'un essaie de comprendre comment inverser l'itération sur une liste de chaînes délimitées par des espaces, cela fonctionne:
Je n'ai pas de tac sur mon système; Je ne sais pas si c'est robuste mais j'utilise for x dans $ {mylist}; do revv = "$ {x} $ {revv}"; fait
arp
@arp C'est un peu choquant comme cela tacfait partie de GNU coreutils. Mais votre solution est également bonne.
ACK_stoverflow
@ACK_stoverflow Il existe des systèmes sans outils utilisateur Linux.
Kusalananda
@Kusalananda Êtes-vous en train de dire que seul Linux utilise des coreutils GNU? LOL. Même busybox l'a fait tac. Bien que d'après le nombre de tacréponses sans réponse ici, je suppose que OSX n'a peut-être pas de tac. Dans ce cas, utilisez une variante de la solution de @ arp - c'est plus facile à comprendre de toute façon.
ACK_stoverflow
@ACK_stoverflow C'est ce que je dis, oui.
Kusalananda
1
find /var/logs/-name 'foo*.log'-print0 | tail -r | xargs -0 bar
Devrait fonctionner comme vous le souhaitez (cela a été testé sur Mac OS X et j'ai une mise en garde ci-dessous ...).
Depuis la page de manuel pour trouver:
-print0This primary always evaluates to true.It prints the pathname of the current file to standard output, followed by an ASCII NUL character (charac-
ter code 0).
Fondamentalement, vous trouvez les fichiers qui correspondent à votre chaîne + glob et vous terminez chacun par un caractère NUL. Si vos noms de fichiers contiennent des sauts de ligne ou d'autres caractères étranges, find devrait bien gérer cela.
tail -r
prend l'entrée standard à travers le tuyau et l'inverse (notez que toutes les entrées sont tail -rimprimées sur stdout, et pas seulement les 10 dernières lignes, ce qui est la valeur par défaut standard. pour plus d'informations).man tail
Nous les canalisons ensuite pour xargs -0:
-0Change xargs to expect NUL (``\0'') characters as separators, instead of spaces and newlines.This is expected to be used in concert with the-print0 functionin find(1).
Ici, xargs s'attend à voir des arguments séparés par le caractère NUL, avec lequel vous avez passé findet inversé tail.
+1 bonne réponse. Il semble cependant qu'Ubuntu ne prend pas en charge tail -r... est-ce que je fais quelque chose de mal?
Mehrdad
1
Non, je ne pense pas que tu l'es. Je n'ai pas ma machine Linux en place mais un rapide google pour 'linux tail man' ne l'affiche pas en option. sunaku mentionné taccomme alternative, donc j'essaierais plutôt
tcdyl
J'ai également modifié la réponse pour inclure une autre alternative
tcdyl
whoops j'ai oublié de +1 quand j'ai dit +1 :( Terminé! Désolé pour ça haha :)
Mehrdad
4
tail -rest spécifique à OSX et inverse les entrées délimitées par des sauts de ligne, et non les entrées délimitées par des valeurs nulles. Votre deuxième solution ne fonctionne pas du tout (vous canalisez l'entrée vers ls, ce qui ne fait rien); il n'y a pas de solution facile qui le rendrait fiable.
Gilles 'SO- arrête d'être méchant'
1
Dans votre exemple, vous bouclez sur plusieurs fichiers, mais j'ai trouvé cette question en raison de son titre plus général qui pourrait également couvrir le bouclage sur un tableau ou l'inversion en fonction d'un certain nombre de commandes.
Voici comment faire cela dans Zsh:
Si vous faites une boucle sur les éléments d'un tableau, utilisez cette syntaxe ( source )
for f in ${(Oa)your_array};do...done
Oinverse l'ordre spécifié dans le drapeau suivant; aest l'ordre normal des tableaux.
Comme l'a dit @Gilles, Oninversera l'ordre de vos fichiers globalisés, par exemple avec my/file/glob/*(On). C'est parce que Onc'est "l' ordre inverse des noms ".
Mac OSX ne prend pas en charge la taccommande. La solution de @tcdyl fonctionne lorsque vous appelez une seule commande dans une forboucle. Pour tous les autres cas, ce qui suit est le moyen le plus simple de le contourner.
Cette approche ne prend pas en charge la présence de nouvelles lignes dans vos noms de fichiers. La raison sous-jacente est que tail -rson entrée est délimitée par des retours à la ligne.
for i in`ls -1 [filename pattern] | tail -r`;do[commands here];done
Cependant, il existe un moyen de contourner la limitation de la nouvelle ligne. Si vous savez que vos noms de fichiers ne contiennent pas un certain caractère (par exemple, '='), vous pouvez utiliser trpour remplacer toutes les nouvelles lignes pour devenir ce caractère, puis effectuer le tri. Le résultat se présenterait comme suit:
Remarque: en fonction de votre version de tr, il peut ne pas être pris en charge en '\0'tant que personnage. Cela peut généralement être résolu en changeant les paramètres régionaux en C (mais je ne me souviens pas exactement, car après l'avoir réparé une fois, cela fonctionne maintenant sur mon ordinateur). Si vous obtenez un message d'erreur et que vous ne trouvez pas la solution de contournement, veuillez la poster en tant que commentaire, afin que je puisse vous aider à le résoudre.
sort -r
avantfor
ou de la laverls -r
.Réponses:
Dans bash ou ksh, placez les noms de fichiers dans un tableau et parcourez ce tableau dans l'ordre inverse.
Le code ci-dessus fonctionne également en zsh si l'
ksh_arrays
option est définie (elle est en mode d'émulation ksh). Il existe une méthode plus simple dans zsh, qui consiste à inverser l'ordre des correspondances via un qualificatif glob:POSIX n'inclut pas de tableaux, donc si vous voulez être portable, votre seule option pour stocker directement un tableau de chaînes est les paramètres positionnels.
la source
i
etf
; effectuez simplement uneshift
, utilisez$1
pour votre appelbar
et testez[ -z $1 ]
votrewhile
.[ -z $1 ]
ni[ -z "$1" ]
les tests (que faire si le paramètre était*
, ou une chaîne vide?). Et en tout cas, cela n'aide pas ici: la question est de savoir comment boucler dans l'ordre inverse.Essayez ceci, sauf si vous considérez les sauts de ligne comme des "personnages géniaux":
la source
f
dans ma situation. Cette réponse, cependant, agit à peu près comme un remplacement sans rendez-vous pour lafor
ligne ordinaire .Si quelqu'un essaie de comprendre comment inverser l'itération sur une liste de chaînes délimitées par des espaces, cela fonctionne:
la source
tac
fait partie de GNU coreutils. Mais votre solution est également bonne.tac
. Bien que d'après le nombre detac
réponses sans réponse ici, je suppose que OSX n'a peut-être pas de tac. Dans ce cas, utilisez une variante de la solution de @ arp - c'est plus facile à comprendre de toute façon.Devrait fonctionner comme vous le souhaitez (cela a été testé sur Mac OS X et j'ai une mise en garde ci-dessous ...).
Depuis la page de manuel pour trouver:
Fondamentalement, vous trouvez les fichiers qui correspondent à votre chaîne + glob et vous terminez chacun par un caractère NUL. Si vos noms de fichiers contiennent des sauts de ligne ou d'autres caractères étranges, find devrait bien gérer cela.
prend l'entrée standard à travers le tuyau et l'inverse (notez que toutes les entrées sont
tail -r
imprimées sur stdout, et pas seulement les 10 dernières lignes, ce qui est la valeur par défaut standard. pour plus d'informations).man tail
Nous les canalisons ensuite pour
xargs -0
:Ici, xargs s'attend à voir des arguments séparés par le caractère NUL, avec lequel vous avez passé
find
et inversétail
.Ma mise en garde: j'ai lu que
tail
cela ne fonctionne pas bien avec des chaînes terminées par null . Cela fonctionnait bien sur Mac OS X, mais je ne peux pas garantir que c'est le cas pour tous les * nix. Faites preuve de prudence.Je dois également mentionner que GNU Parallel est souvent utilisé comme
xargs
alternative. Vous pouvez également vérifier cela.Il me manque peut-être quelque chose, alors les autres devraient sonner.
la source
tail -r
... est-ce que je fais quelque chose de mal?tac
comme alternative, donc j'essaierais plutôttail -r
est spécifique à OSX et inverse les entrées délimitées par des sauts de ligne, et non les entrées délimitées par des valeurs nulles. Votre deuxième solution ne fonctionne pas du tout (vous canalisez l'entrée versls
, ce qui ne fait rien); il n'y a pas de solution facile qui le rendrait fiable.Dans votre exemple, vous bouclez sur plusieurs fichiers, mais j'ai trouvé cette question en raison de son titre plus général qui pourrait également couvrir le bouclage sur un tableau ou l'inversion en fonction d'un certain nombre de commandes.
Voici comment faire cela dans Zsh:
Si vous faites une boucle sur les éléments d'un tableau, utilisez cette syntaxe ( source )
O
inverse l'ordre spécifié dans le drapeau suivant;a
est l'ordre normal des tableaux.Comme l'a dit @Gilles,
On
inversera l'ordre de vos fichiers globalisés, par exemple avecmy/file/glob/*(On)
. C'est parce queOn
c'est "l' ordre inverse des noms ".Indicateurs de tri Zsh:
a
ordre du tableauL
longueur du fichierl
nombre de liensm
date de modificationn
prénom^o
ordre inverse (o
est un ordre normal)O
ordre inversePour des exemples, voir https://github.com/grml/zsh-lovers/blob/master/zsh-lovers.1.txt et http://reasoniamhere.com/2014/01/11/outrageously-useful-tips- maîtriser votre shell z /
la source
Mac OSX ne prend pas en charge la
tac
commande. La solution de @tcdyl fonctionne lorsque vous appelez une seule commande dans unefor
boucle. Pour tous les autres cas, ce qui suit est le moyen le plus simple de le contourner.Cette approche ne prend pas en charge la présence de nouvelles lignes dans vos noms de fichiers. La raison sous-jacente est que
tail -r
son entrée est délimitée par des retours à la ligne.Cependant, il existe un moyen de contourner la limitation de la nouvelle ligne. Si vous savez que vos noms de fichiers ne contiennent pas un certain caractère (par exemple, '='), vous pouvez utiliser
tr
pour remplacer toutes les nouvelles lignes pour devenir ce caractère, puis effectuer le tri. Le résultat se présenterait comme suit:Remarque: en fonction de votre version de
tr
, il peut ne pas être pris en charge en'\0'
tant que personnage. Cela peut généralement être résolu en changeant les paramètres régionaux en C (mais je ne me souviens pas exactement, car après l'avoir réparé une fois, cela fonctionne maintenant sur mon ordinateur). Si vous obtenez un message d'erreur et que vous ne trouvez pas la solution de contournement, veuillez la poster en tant que commentaire, afin que je puisse vous aider à le résoudre.la source
un moyen simple est d'utiliser
ls -r
comme mentionné par @David Schwartzla source
Essaye ça:
Je pense que c'est le moyen le plus simple.
la source
for
boucle dans l'ordre inverse».