Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 11/06/2012, à 11:19

mixout

[RESOLU] copie fichiers et repertoires conteneurs

Bonjour
j'ai déjà posté une question similaire mais visiblement pas dans la bonne section du forum
je suis en train de faire du rangement dans différents disques durs (photos, musique, films)

j'ai déjà obtenu des résulats avec la commande

find /chemin/contenant/plusieurs/sousrepertoire/contenant/chacun/des/photos -name '*.jpg' -exec mv {} /nouveau/chemin \;

le problème, c'est que cela me détruit une organisation qui était déjà existante et que les photos sont déplacées "sans " leur répertoire source

par exemple si la commande rencontre un dossier appelé "photos_noel" je souhaiterais que la commande copie les photos contenues dans ce répertoire ET son répertoire,pas seulement les fichiers.
il a-t-il un autre moyen qu'a la souris/petite cuillère ?

merci par avance

Dernière modification par mixout (Le 11/06/2012, à 15:04)

Hors ligne

#2 Le 11/06/2012, à 12:31

pingouinux

Re : [RESOLU] copie fichiers et repertoires conteneurs

Bonjour,
Ceci devrait faire l'affaire :

#!/bin/bash

shopt -s globstar

cd repertoire_de_base
for i in **/*.jpg
do
   cp -p --parents "$i" repertoire_de_destination
 # rm -i "$i"
done

Décommenter le rm si c'est bon

Hors ligne

#3 Le 11/06/2012, à 13:25

nesthib

Re : [RESOLU] copie fichiers et repertoires conteneurs

tu n'as pas choisi la bonne section du forum… Trucs et Astuces est fait pour proposer des Trucs et Astuces, pas pour demander de l'aide. Je déplace dans une section plus indiquée.

sinon je n'ai pas testé la méthode de pingouinux, mais selon les version de bash la syntaxe

for i in *

peut mener à des résultats catastrophiques (mauvaise gestion des espaces et caractères spéciaux des noms de fichiers par exemple)
autre problème, utiliser cp+rm à la place de mv force un accès disque en lecture/écriture non nécessaire, là où mv se contente de modifier le nom dans le système de fichiers (ceci n'est cependant vrai que si l'on reste sur la même partition).

personnellement je ferais :

DESTINATION='/nouveau/chemin/'
while read file
do
  [ ! -d "${DESTINATION%/}/${file%/*}" ] && { echo "créaton de "${DESTINATION%/}/${file%/*}" ; mkdir -p "${DESTINATION%/}/${file%/*}" ; }
  mv "${file}" "${DESTINATION%/}/${file}"
done < <(find /chemin/contenant/plusieurs/sousrepertoire/contenant/chacun/des/photos -iname '*.jpg')

tu remarqueras l'utilisation des guillemets simples autour des variables contenant les noms de fichiers, et le iname (non sensible à la casse ; soit *.jpg mai aussi *.JPG)
DESTINATION peut se terminer ou non par un « / »


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#4 Le 11/06/2012, à 14:39

pingouinux

Re : [RESOLU] copie fichiers et repertoires conteneurs

@nesthib #3 : D'accord avec ta remarque. for i in * fonctionne sans problème avec cette version de bash :

GNU bash, version 4.2.8(1)-release (x86_64-pc-linux-gnu)

Hors ligne

#5 Le 11/06/2012, à 15:03

mixout

Re : [RESOLU] copie fichiers et repertoires conteneurs

Merci pingouinux et nesthib
j'ai toutes les précisions qu'il me faut

Hors ligne

#6 Le 11/06/2012, à 18:13

Postmortem

Re : [RESOLU] copie fichiers et repertoires conteneurs

Salut,

nesthib a écrit :

sinon je n'ai pas testé la méthode de pingouinux, mais selon les version de bash la syntaxe

for i in *

peut mener à des résultats catastrophiques (mauvaise gestion des espaces et caractères spéciaux des noms de fichiers par exemple)

Je pense au contraire que pour boucler sur les fichiers le for i in * est plus sûr que le find tel qu'il est indiqué ici.
for i in * gère très bien les espaces et autres car le découpage en mots de la ligne de commande a lieu avant l'expansion de *.

Petit exemple :

$ touch '   fichier avec espaces au début et à la fin    ' fichier 'fichier avec
> retour à la ligne'

$ for i in *; do ls -l "$i"; done
-rw-rw-r-- 1 xxxx xxxx 0 juin  11 17:57 fichier
-rw-rw-r-- 1 xxxx xxxx 0 juin  11 17:57    fichier avec espaces au début et à la fin    
-rw-rw-r-- 1 xxxx xxxx 0 juin  11 17:57 fichier avec?retour à la ligne

$ while read file; do ls -l "$file"; done < <(find . -type f)
ls: impossible d'accéder à ./fichier avec: Aucun fichier ou dossier de ce type
ls: impossible d'accéder à retour à la ligne: Aucun fichier ou dossier de ce type
-rw-rw-r-- 1 xxxx xxxx 0 juin  11 17:57 ./fichier
ls: impossible d'accéder à ./   fichier avec espaces au début et à la fin: Aucun fichier ou dossier de ce type

Pour que le find fonctionne correctement :

$ while read -rd ''; do ls -l "$REPLY"; done < <(find . -type f -print0)
-rw-rw-r-- 1 xxxx xxxx 0 juin  11 17:57 ./fichier avec?retour à la ligne
-rw-rw-r-- 1 xxxx xxxx 0 juin  11 17:57 ./fichier
-rw-rw-r-- 1 xxxx xxxx 0 juin  11 17:57 ./   fichier avec espaces au début et à la fin

Ou, pour que l'on puisse utiliser la variable que l'on veut :

$ while IFS= read -rd '' file; do ls -l "$file"; done < <(find . -type f -print0)
-rw-rw-r-- 1 xxxx xxxx 0 juin  11 17:57 ./fichier avec?retour à la ligne
-rw-rw-r-- 1 xxxx xxxx 0 juin  11 17:57 ./fichier
-rw-rw-r-- 1 xxxx xxxx 0 juin  11 17:57 ./   fichier avec espaces au début et à la fin

Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#7 Le 11/06/2012, à 22:00

nesthib

Re : [RESOLU] copie fichiers et repertoires conteneurs

@Postmortem : le support correct de « for i in * » est relativement récent dans bash (et c'est une très bonne chose !). Si tu parcours ce forum et d'autres, tu trouveras que le problème du « for i in * » est très courant et affecte beaucoup de scripts. Effectivement le retour de ligne n'est pas pris en compte avec la boucle « while read line » en utilisant le séparateur par défaut, mais d'une part ce cas de figure est extrêmement rare, d'autre part il est facilement gérable avec une modification de l'IFS comme tu le précises.
Je ne dis pas que la méthode du « for » ne fonctionne pas, moi même je l'utilise fréquemment. Je mets simplement en garde un éventuel utilisateur des risques qui y sont liés car il n'y a pas si longtemps ce problème était récurrent. De plus, si le script doit être partagé, la version en « while read line » sera plus portable.
En conclusion il y a plusieurs solutions, ensuite chacun fait comme il veut, mais il vaut mieux être au courant des avantages et inconvénients de chaque solution.


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#8 Le 12/06/2012, à 06:08

Postmortem

Re : [RESOLU] copie fichiers et repertoires conteneurs

Merci pour tes précisions nesthib. Je pensais que la boucle for en bash gérait ça correctement depuis très longtemps (voir son origine) car au taf, on utilise ksh, qui n'est pas tout jeune, et qui gère ça correctement.

Edit :
En fait, le problème avec la boucle for vient plus de ce genre de construction je pense : for fic in $(ls *.jpg).
for fic in * ne pose pas de souci tant que l'on pense à protéger la variable $fic avec des double-quotes dans la suite du traitement.
En tout cas, pas de problème en bash 3, en ksh ni en sh.

Dernière modification par Postmortem (Le 12/06/2012, à 08:43)


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne