web-dev-qa-db-fra.com

Puis-je utiliser le terminal pour déplacer des images vers des répertoires spécifiques en utilisant la balise images?

J'ai un énorme dossier d'images que j'ai collectées au fil des années que mes élèves utilisent pour les cours. Cela a commencé avec une vingtaine d'images, donc je ne me suis pas vraiment soucié des noms de fichiers ou de toute sorte de structure, je les ai simplement marqués et glanés dedans. Ce même dossier contient maintenant environ 5000 images et il arrive au point où c'est difficile travailler avec.

Idéalement, j'aimerais pouvoir exécuter une commande (maintenant et à l'avenir à mesure que d'autres seront soumises) qui examinerait les balises images et créerait un répertoire avec le nom de la balise et y déplacerait cette image, ou si une image précédente a déjà créé ce répertoire, déplacez simplement l'image dans ce répertoire.

Je ne suis pas sûr de bien expliquer cela.

Les 5 premières images par exemple sont des voitures - BMW, Honda, Ford, Alfa Romeo et une autre BMW. Les noms de fichiers sont tous uniques - ils sont tous dans le même dossier, souvenez-vous. Donc, après avoir exécuté ce script mythique, j'aurais 4 dossiers avec les 2 images dans celui de BMW.

Tout est étiqueté dans Shotwell, il s'agit principalement de JPG avec quelques PNG ajoutés juste pour compliquer les choses! Il peut y avoir plusieurs balises mais 95% ne sont que des balises uniques. Je ne sais pas où les balises sont stockées, mais je suppose que dans chaque fichier, car les balises apparaissent sur mes deux ordinateurs, mais n'ont jamais été balisées sur le principal.

Une enquête plus approfondie a montré que les balises sont stockées par rapport aux "mots-clés" de l'image individuelle, alors je devrais peut-être demander comment créer des répertoires en fonction de ses mots-clés?

J'apprends beaucoup en allant ici!

Si cela aide, voici la sortie du exiftool:

$ exiftool 010.jpg
ExifTool Version Number         : 10.10
File Name                       : 010.jpg
Directory                       : .
File Size                       : 274 kB
File Modification Date/Time     : 2016:04:23 21:03:59+01:00
File Access Date/Time           : 2016:04:23 21:03:59+01:00
File Inode Change Date/Time     : 2016:04:23 21:03:59+01:00
File Permissions                : rw-rw-r--
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.01
Resolution Unit                 : inches
X Resolution                    : 72
Y Resolution                    : 72
Exif Byte Order                 : Little-endian (Intel, II)
Software                        : Shotwell 0.22.0
XMP Toolkit                     : XMP Core 4.4.0-Exiv2
Subject                         : BMW, Bell_Photography
Current IPTC Digest             : 6249bf63f46e9abb15cfe27d71a87a72
Keywords                        : BMW, Bell_Photography
Originating Program             : Shotwell
Program Version                 : 0.22.0
Image Width                     : 936
Image Height                    : 1334
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:4:4 (1 1)
Image Size                      : 936x1334
Megapixels                      : 1.2

En supposant que cela ait du sens pour tout le monde sauf moi, est-ce possible?

1
Dave

Vous pouvez utiliser exiftool , pour obtenir des méta-informations à partir de fichiers jpg, png. Pour installer exiftool, exécutez:

$ Sudo apt-get install libimage-exiftool-Perl

Utilisation: exiftool -s example.jpg

Il semble que les informations les plus complètes soient stockées sous la forme TagsList. Il prend même en charge les balises hiérarchiques enregistrées par Shotwell, par exemple, nature/sky. Les balises se trouvent également dans les champs Subject, Keywords, LastKeywordXMP. Subject, Keywords ne conserve pas la hiérarchie des balises - vous pouvez les utiliser si vous ne souhaitez pas créer de répertoires imbriqués pour les balises imbriquées.

Voici python3 script qui déplace les fichiers image spécifiés sur la ligne de commande vers les répertoires de balises correspondants (en créant des liens physiques et en supprimant le nom de fichier d'origine), par exemple, si example.jpg a la liste des balises: nature, nature/clouds, nature/mountain, nature/sky alors l'arborescence du répertoire des résultats ressemble à:

.
└── nature
    ├── clouds
    │   └── example.jpg
    ├── example.jpg
    ├── mountain
    │   └── example.jpg
    └── sky
        └── example.jpg

Remarque: sauvegardez toujours vos données avant d'exécuter des commandes potentiellement destructrices (des bugs se produisent) :

#!/usr/bin/env python3
"""Move image files to their tag directories by creating hardlinks.

Usage: move-to-tag-dirs <image>...
"""
import json
import os
import sys
from subprocess import Popen, PIPE

TAGNAMES = ['TagsList', 'Keywords', 'Subject']
__version__ = '0.3.1'


def move_to_dirs(filename, dirs):
    """Move *filename* to *dirs* by creating hardlinks.

    Create destination directories if they don't exist.
    """
    for dirname in dirs:
        os.makedirs(dirname, exist_ok=True)
        dest_filename = os.path.join(dirname, os.path.basename(filename))
        os.link(filename, dest_filename)  # create hardlink
    if dirs:  # created at least one new link
        os.unlink(filename)  # remove old


if len(sys.argv) < 2:
    sys.exit(__doc__)  # print usage

command = ['exiftool', '-json'] + ['-' + t for t in TAGNAMES] + sys.argv[1:]
try:
    process = Popen(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
except OSError as e:
    sys.exit("error: can't start exiftool: " + str(e))
else:
    output, errors = process.communicate()
    if process.returncode != 0:
        sys.exit("error: can't read tags info: exiftool exit code: %d: %s" % (
            process.returncode, errors))

for metadata in json.loads(output):
    # get first available tags list
    dirs = next(filter(None, map(metadata.get, TAGNAMES)), [])
    if isinstance(dirs, str):  # single tag
        dirs = [dirs]
    try:
        move_to_dirs(metadata['SourceFile'], dirs)
    except OSError as e:
        print("warning: failed to move %s to %s: %s" % (
            metadata['SourceFile'], dirs, e), file=sys.stderr)

Enregistrez-le dans un fichier nommé move-to-tag-dirs Quelque part dans $PATH . Assurez-vous que le fichier dispose d'autorisations exécutables:

$ chmod +x move-to-tag-dirs

Connexes: Comment exécuter un programme .py directement?

Ensuite, pour déplacer toutes les images vers les répertoires de balises correspondants, exécutez:

$ move-to-tag-dirs *.jpg *.png

Si vous obtenez 'Argument list too long' erreur puis exécutez:

$ find . -maxdepth 1 -name \*.jpg -o -name \*.png -exec move-to-tag-dirs {} +

Voir Résolution de "mv: Liste d'arguments trop longue"?

Si vous ignorez la gestion des erreurs, la prise en charge des balises hiérarchiques, la prise en charge des caractères inhabituels dans les noms de fichiers, les balises, etc., le script pourrait être considérablement simplifié (peut-être, un simple script Shell unique serait suffisant dans ce cas).

3
jfs

Bien que la réponse de J. F. Sebastian soit probablement ce que vous recherchez, il existe également un système de fichiers basé sur des balises nommé tagsistant qui pourrait valoir la peine d'être étudié. Vous pouvez traiter vos balises comme des répertoires dans les systèmes de fichiers conventionnels et parcourir vos fichiers par navigation. Cela rend plus facile si vous avez plusieurs balises dans un fichier et que vous souhaitez les rechercher et les trier.

3
emk2203