Forum Programmation.shell Recréation d'arborescence et de contenu

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
2
29
sept.
2020

Bonjour à toutes et tous,

Je vous explique mon problème. Je dois, pour les besoins d'un projet, pouvoir recréer toute une arborescence de répertoires, sous-répertoires et fichiers, en parcourant une arborescence existante.

Dans ce cadre, je dois recréer exactement la structure de l'arborescence (même nom de répertoire, de sous-répertoire, etc …). Et lorsque j'arrive à une feuille de l'arborescence (au niveau des fichiers), au lieu de copier le fichier original, je dois créer dans la nouvelle arborescence ainsi créée, un fichier de même nom, par la commande touch par exemple.

L'objectif est de recréer une arborescence de fichiers de production, dans un nouveau filesystem, sans recopier les fichiers eux-mêmes pour des raisons d'anonymisation des données.

Je me heurte à des difficultés liées à la présence de caractères spéciaux dans les noms des fichiers de l'arborescence source : espaces, {, }, etc …

J'ai écrit ce script :

#!/bin/sh

RACINE=/home/user/Téléchargements
DEST=/home/user/TestCopie

cd $RACINE
find . -type d | while read dossier; do
    mkdir -p "$DEST/$dossier"
done

find . -type f | while read fichier; do
        dossier=$DEST/`dirname "$fichier"`
    touch $dossier/$fichier
    done
#done

Je ne suis pas sûr qu'il puisse finalement m'amener au résultat escompté.

Je vous remercie pour votre aide.

Bonne journée.

  • # interpretation des variables

    Posté par  . Évalué à 2. Dernière modification le 29 septembre 2020 à 12:47.

    la logique est bonne,

    c'est la manière dont le shell interprète la variable qu'il faut modifier

    $fichier va prendra la variable telle quelle, et s'il y a des espaces, ou des caractères spéciaux, va les afficher

    ta commande touch va donc ressembler à

    touch mon dossier avec espace/mon fichier à copier

    ce qui n'est pas ce que tu souhaites.

    il y a la forme

    touch ${dossier}/${fichier}

    ou la forme

    touch '$dossier'/'$fichier'

    qui devrait pouvoir convenir.

    • [^] # Re: interpretation des variables

      Posté par  (site web personnel) . Évalué à 2. Dernière modification le 30 septembre 2020 à 08:26.

      Ce qui est étonnant c'est que le mkdir est bien quoté mais pas le touch. La règle c'est : tout quoter, t'aura pas de problème.

      « Il vaut mieux mobiliser son intelligence sur des conneries que mobiliser sa connerie sur des choses intelligentes. »

      • [^] # Re: interpretation des variables

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

        Il faut utiliser des " et pas des ' vu que la variable doit être interprétée.

        Ensuite non ça ne suffit pas forcément.

        Exemple :

        $ toto="--help" ; touch "$toto"
        Utilisation : touch [OPTION]... FICHIER...
        $ toto="--help" ; touch -- "$toto"
        $
  • # Presque ?

    Posté par  . Évalué à 2.

    Dans la deuxième étape, pourquoi passer par

    dossier=$DEST/`dirname "$fichier"`

    ?

    Est-ce que

    touch "$DEST/$fichier"

    fait l'affaire ?
    (avec les guillemets en plus)

    D'ailleurs, à la réflexion, un

    echo touch $dossier/$fichier

    devrait afficher des chemins pour le moins troublants …

    • [^] # Re: Presque ?

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

      touch "$DEST/$fichier"

      Ben oui, c'est bien ce qu'il faut faire!

      echo touch $dossier/$fichier

      et ceci est un conseil des plus valables!

      Dans les programmes plus compliqués j'aime bien faire quelque chose comme

      touch()
      {
         echo "Debug: touch" "$@"
         command touch "$@"
      }
      

      pour tracer les appels à un programme extérieur.

  • # -exec + mini-script

    Posté par  . Évalué à 2.

    find "$RACINE" -type f -exec sh -c 'rep=${1%/*}; fic=${1##*/}; mkdir -p "$3/${rep#$2}" && >"$3/${rep#$2}/$fic"' _ {} "$RACINE" "$DEST" \;
  • # rsync

    Posté par  . Évalué à 3.

    rsync -av -f"+ */" -f"- *" /path/to/src /path/to/dest/

    source

  • # En Perl

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

    Sinon, avec un langage qui n’est pas assez idiot pour interpréter ses variables avant d’analyser la ligne de commande, ça évite quand même bien des surprises et incertitudes :

    #!/usr/bin/perl -w
    use strict;
    
    use Cwd;
    use File::Find;
    
    @ARGV == 2 or die "Recrée une arborescence avec des fichiers vides.\nUtilisation : $0 repertoire_source repertoire_destination\n";
    
    my ($src, $dst) = @ARGV;
    
    # Avant de se placer dans le répertoire source, il faut s’assurer d’avoir le
    # chemin absolu du répertoire destination.
    $dst =~ m{^/} or $dst = getcwd . "/$dst";
    
    chdir $src or die "Impossible d’accéder à $src\n";
    -d $dst or mkdir $dst or die "Impossible de créer $dst\n";
    
    sub cree {
        # Attention, les liens symboliques ne sont pas gérés !
        if (-d) {
            -d "$dst/$File::Find::name" or mkdir "$dst/$File::Find::name" or warn "Impossible de créer le répertoire $dst/$File::Find::name\n";
        } elsif (-f) {
            open my $fich, '>', "$dst/$File::Find::name" or warn "Impossible de créer le fichier $dst/$File::Find::name\n";
        }
        # Les pipes, devices ou autres sont ignorés.
    }
    
    find(\&cree, '.');

    Prendre une bonne disposition : beop.free.fr

    • [^] # Re: En Perl

      Posté par  . Évalué à 1.

      Houla,

      Je découvre la suite des réponses qui m'ont été faites suite à l'exposé de mon problème.

      Je m'aperçois que j'avais mal réglé la façon dont j'étais prévenu des réponses.

      Je vous remercie infiniment pour les éléments apportés. Je vais m'attacher à tester les solutions.

      Je vous remercie mille fois et vous ferai un retour.

      Bonne journée.

Suivre le flux des commentaires

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