Forum Programmation.shell find, sort & nul char

Posté par  . Licence CC By‑SA.
Étiquettes :
2
30
nov.
2016

Bonjour,

J’ai un script qui stock l’état des permissions d’un répertoire dans un fichier. Pour comparer l’état courant avec l’état sauvegardé je procède ainsi :

function check() {

    diff -aBy <(cat $1) <(store $2) | tr "\000" " " |egrep '\s\||>|<\s'
}

$1 est mon fichier dans lequel sont stockés les permissions
$2 est le répertoire concerné

Le fichier est généré ainsi (c’est la fonction 'store' utilisée ci-dessus) :

function store() {

    find "$1" -printf "%u\000%g\000%m\000%h/%f\n"
}

(ici $1 est le répertoire concerné)

J’obtiens ce genre d’output :

stef stef 640 ./README.md                         | stef staff 600 ./README.md
stef stef 750 ./.git                          | stef stef 710 ./.git

C’est super, c’est exactement ce que je veux, un moyen d’avoir rapidement une vue sur d’éventuelles modifications des droits ou sur l’ajout de nouveaux fichiers dans une arborescence.

Quelque temps plus tard je me suis dit : « Hé patate ! Tu ne sais pas si l’ordre (des fichiers en sortie de la commande find) sera toujours le même, tu devrais trier ! »

Quand je commence à m’appeler patate, je fais pas le malin et je m’obéis… donc je fais ça :

diff -aBy <(sort $1) <(store $2 | sort) | tr "\000" " " |egrep '\s\||>|<\s'

et là patatra je n’ai plus le même résultat :

                                  > stef staff 600 ./README.md
stef stef 750 ./.git                          | stef stef 710 ./.git

il m’en manque un bout (et parfois j’ai un décalage d’une ligne).

J’ai le même comportement si j’effectue le sort à l’intérieur de la fonction 'store'.

Je ne comprends pas pourquoi.

Comment puis-je m’assurer de comparer deux sorties de find (entre une exécution de store et l’exécution précédente stockée dans un fichier) qui soient toujours dans le même ordre ? (Est-ce que nativement find crache les fichiers toujours dans le même ordre ?)

Est-ce que ce serait l’utilisation du caractère nul qui me joue des tours ici ? D’après ce que je lis, il n’est pas possible de stocker une chaîne contenant ce caractère dans une variable mais tubes et redirections ne devraient pas poser de problème.

  • # c'est possible

    Posté par  . Évalué à 2.

    pourquoi ne pas alors stocker simplement tes resultats en CSV
    %u;%g;%file

    le sort devrait alors fonctionner,
    tu pourrais aussi ouvrir le fichier dans un tableur, etc

    • [^] # Re: c'est possible

      Posté par  . Évalué à 2.

      L’utilisation du caractère nul plutôt qu’un point-virgule c’est parce que c’est le seul caractère que je suis assuré de ne pas rencontrer dans le chemin d’un fichier… alors que le point virgule :

      $ touch 'tl;dr'
      $ ll t*
      -rw-r--r-- 1 stef stef 0 nov.  30 23:47 tl;dr
      

      Si j’ai un fichier avec ce genre de nom, pouf le script (il prendrait 'tl' comme nom de fichier)…

      Il y aurait aussi la solution de ne spliter qu’un nombre restreint de colonnes (les trois premières) mais ça devient plus compliqué avec awk…

      Donc j’aimerais d’abord être sûr que c’est à cause du caractère nul comme séparateur que j’ai ce comportement. D’après la lecture du manuel ça ne devrait pas poser de problème.

  • # find... | sort ?

    Posté par  . Évalué à 2.

    Et en faisant un sort au moment du find ?

    Je ne me suis pas remis exactement dans tes conditions,
    mais ça semble marcher :

    $ find . -printf "%u \000%g \000%m %f\n" |sort -t" " -k4
    frayd frayd 775 .
    frayd frayd 764 azerty.bash
    frayd frayd 664 BIDON
    frayd frayd 775 BIDON-MIROIR
    frayd frayd 764 cmpfic.pl
    frayd frayd 664 fichier-test.txt
    frayd frayd 664 fictest1
    frayd frayd 664 fictest2
    • [^] # Re: find... | sort ?

      Posté par  . Évalué à 3.

      Ah oui mais tu triches ! Tu ajoutes une espace comme séparateur…

      Comme j’ai écrit, j’ai bien la même chose si je fais le sort au moment du find.

      Cela dit merci quand même pour ton commentaire, j’essaierai en faisant sort -t"\000" -k4

      • [^] # Re: find... | sort ?

        Posté par  . Évalué à 1.

        Arf…
        Désolé, j'ai cru que l'absence d'espaces dans ton exemple était une erreur de typo…

  • # sdiff ?!

    Posté par  (site web personnel) . Évalué à 1.

    sdiff n'est pas suffisant pour ce que tu veux faire ?

    : sdiff <(find expire/ -printf "%u\000%g\000%m\000%h/%f\n" | tr "\000" " ") <(find expire/bash-4.3.42-3.fc23.x86_64/ -printf "%u\000%g\000%m\000%h/%f\n" | tr "\000" " ")
    
    testuser testgrp 755 expire/xpa-2.4-3-build1929                 <
    testuser testgrp 644 expire/xpa-2.4-3-build1929/magicxpa_2.4c-3 <
    testuser testgrp 644 expire/xpa-2.4-3-build1929/magicxpa_2.4c-3 <
    testuser testgrp 755 expire/bash-4.3.42-3.fc23.x86_64           <
    testuser testgrp 755 expire/bash-4.3.42-3.fc23.x86_64/usr         testuser testgrp 755 expire/bash-4.3.42-3.fc23.x86_64/usr
    testuser testgrp 755 expire/bash-4.3.42-3.fc23.x86_64/usr/bin     testuser testgrp 755 expire/bash-4.3.42-3.fc23.x86_64/usr/bin
    testuser testgrp 777 expire/bash-4.3.42-3.fc23.x86_64/usr/bin/b   testuser testgrp 777 expire/bash-4.3.42-3.fc23.x86_64/usr/bin/b
    testuser testgrp 777 expire/bash-4.3.42-3.fc23.x86_64/usr/bin/s   testuser testgrp 777 expire/bash-4.3.42-3.fc23.x86_64/usr/bin/s
    testuser testgrp 755 expire/bash-4.3.42-3.fc23.x86_64/usr/share   testuser testgrp 755 expire/bash-4.3.42-3.fc23.x86_64/usr/share
    testuser testgrp 755 expire/bash-4.3.42-3.fc23.x86_64/usr/share   testuser testgrp 755 expire/bash-4.3.42-3.fc23.x86_64/usr/share
    testuser testgrp 755 expire/bash-4.3.42-3.fc23.x86_64/usr/share   testuser testgrp 755 expire/bash-4.3.42-3.fc23.x86_64/usr/share
    testuser testgrp 777 expire/bash-4.3.42-3.fc23.x86_64/usr/share   testuser testgrp 777 expire/bash-4.3.42-3.fc23.x86_64/usr/share
    testuser testgrp 777 expire/bash-4.3.42-3.fc23.x86_64/usr/share   testuser testgrp 777 expire/bash-4.3.42-3.fc23.x86_64/usr/share
    testuser testgrp 755 expire/bash-4.3.33-2.fc22.i686             <
    testuser testgrp 755 expire/bash-4.3.33-2.fc22.i686/usr         <
    testuser testgrp 755 expire/bash-4.3.33-2.fc22.i686/usr/bin     <
    testuser testgrp 777 expire/bash-4.3.33-2.fc22.i686/usr/bin/bas <
    testuser testgrp 777 expire/bash-4.3.33-2.fc22.i686/usr/bin/sh  <
    testuser testgrp 755 expire/bash-4.3.33-2.fc22.i686/usr/share   <
    testuser testgrp 755 expire/bash-4.3.33-2.fc22.i686/usr/share/m <
    testuser testgrp 755 expire/bash-4.3.33-2.fc22.i686/usr/share/m <
    testuser testgrp 777 expire/bash-4.3.33-2.fc22.i686/usr/share/m <
    testuser testgrp 777 expire/bash-4.3.33-2.fc22.i686/usr/share/m <
    
    • [^] # Re: sdiff ?!

      Posté par  . Évalué à 2.

      Je n’ai pas eu le temps de me re-pencher sur ce projet mais sdiff est probablement ce que je cherche. Merci pour ton test !

      Ce qui voudrait dire que sdiff n’est pas équivalent à diff -y…

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.