Bonjour,
Cette semaine, c’est un poil technique. Si vous ne maîtrisez pas bien les fondamentaux de R, vous serez sans doute un peu perdu. N’hésitez pas à consulter nos formations si vous êtes dans ce cas.
Cette semaine, une collègue et amie m’a soumis un problème assez rigolo : elle a un fichier excel qui contient les chemins d’accès à plein d’images, ainsi que les caractéristiques de ces images. Ce qu’elle voudrait faire, c’est choisir les images qui correspondent aux caractéristiques qui lui plaisent (par exemple le lieu où la photo a été prise, la collection à laquelle la photo appartient, etc), et déplacer les images dans un dossier spécifique.
Choisir les images par critère, ça c’est facile, c’est la base de la manipulation de données dans R. Mais déplacer des fichiers, c’est un peu différent. Alors bien sûr on pourrait faire un script qui fait ça en bash, ou en python, mais si on ne connaît que R, on peut s’en sortir.
Donc, on va essayer de bidouiller un script qui permet, à partir d’un vecteur de chemins d’accès à des fichiers, de déplacer tous ces fichiers dans un nouveau dossier. On va même ajouter une barre de progression, pour la beauté.
Le premier enjeu, c’est de récupérer les chemins d’accès. Donc, dans mon data.frame, j’ai une colonne Image.Path, qui contient les chemins d’accès aux images, de cette façon:
« /MJL/2018/02/21/CP1_20180221_BATCH_0001/tif/LAU-0000565.tif »
Donc nous on doit choper chacun des fichiers, et le copier ailleurs. Dans un premier temps, on s’assure que les chemins sont bien considérés comme des chaînes de caractères, et pas des facteurs :
data$Image.Path <- as.character(data$Image.Path)
Ensuite, on récupère le nom du fichier. Pour ça c’est facile, on se rend compte que le chemin d’accès est séparé par le caractère « / ». Donc il suffit de découper le chemin à chaque fois que ce caractère apparaît, et de récupérer le dernier bloc.
Bon, tavaillons avec un seul chemin déjà, qu’on stocke dans une variable file_path. On peut générer une liste de chaque partie du chemin délimitée par un caractère « / »:
path_split <- strsplit(file_path, "/")
L’objet path_split contient maintenant notre chemin découpé. Nous on veut récupérer le dernier bloc. Donc d’abord, on calcule le nombre de bouts qu’il y a dans le chemin avec :
len_path <- length(path_split[[1]])
len_path est une variable qui contient maintenant le nombre de parties dans le chemin. On utilise [[1]] parce que path_split est une liste de longueur 1, et quand on veut accéder au contenu d’une liste, on utilise les doubles crochets.
Ensuite on récupère le dernier bloc, qui est en fait le bloc qui se trouve à l’index de valeur len_path. Si le chemin est découpé en 5 parties, alors len_path vaut 5, et le bloc en 5ème position est le nom du fichier, donc :
file_name <- path_split[[1]][len_path]
Super, on a déjà bien avancé. Maintenant, il ne reste plus qu’à déplacer ce fichier où l’on veut, et pour ça on va utiliser la fonction file.copy(). Pour utiliser file.copy on doit lui fournir un emplacement d’origine (ça on l’a), et un emplacement de destination. Il faut donc construire le chemin de destination. J’ai pris le parti de créer un dossier pictures dans mon répertoire courant. Je veux donc créer un chemin de type :
répertoire_courant/pictures/file_name
C’est là qu’on est content d’avoir récupéré le nom du fichier !
Je vais construire le chemin pas à pas. On récupère le nom du répertoire courant avec getwd(). Si on veut ajouter des choses à ce chemin, on le fait avec la commande file.path(). Donc par exemple :
new_file <- file.path(getwd(),"pictures", filename)
va créer un chemin qui contient le nouvel emplacement de notre image. Il ne reste plus qu’à faire :
file.copy(from = file_path, to = new_file),
et on a fini.
Reste plus qu’à envelopper tout ça dans une belle boucle, à ajouter une barre de progression, et à mettre tout ça dans une fonction et on obtient le code en bas de page. L’intérêt de faire un beau code dans une fonction, c’est qu’ensuite ça devient aussi simple de déplacer 30 fichiers ou bien 10 000.
move_pictures <- function(picture_path, future_dir){
# picture_path est un vecteur contenant les chemins d'origine
# future_dir est uen chaine de caractères contenant le nom du dossier de destination. Par exemple "clean_pictures"
#chope le répertoire courant et crée le dossier de destination si il n'existe pas
new_path <- file.path(getwd(),future_dir)
if(!dir.exists(new_path)){
dir.create(new_path)
}
#initialise progress bar
pb <- txtProgressBar(min=1, max = length(picture_path), style = 3)
i=0
cat("Moving", length(picture_path), "files\n")
#boucle sur les paths
for(file_path in picture_path){
i = i +1
setTxtProgressBar(pb, i)
len_path <- length(strsplit(file_path, "/")[[1]])
file_name <- strsplit(file_path, "/")[[1]][len_path]
#copy file to new_path/file_name
file.copy(from = file_path, to = file.path(new_path,file_name))
#cat(file.path(new_path,file_name))
}
#close progress bar
close(pb)
Restez informé !
Inscrivez-vous à la Newsletter pour être tenu au courant des nouveaux articles
Commentaires récents