web-dev-qa-db-ja.com

端末を使用して、画像の「タグ」を使用して特定のディレクトリに画像を移動できますか?

私は学生が授業で使用するために長年にわたって収集した画像の巨大なフォルダを持っています。約20枚の画像から始まったので、ファイル名や構造を気にせず、タグ付けしてチャックするだけでした。同じフォルダに約5000枚の画像があり、難しいところに到達していますで動作します。

理想的には、画像タグを見て、タグの名前でディレクトリを作成し、その画像をその中に移動するコマンドを実行できるようになります(現在および将来、さらに送信されます)。または、以前のイメージが既にそのディレクトリを作成している場合は、単にそのディレクトリにイメージを移動します。

これを説明するのに非常に良い仕事をしているかどうかはわかりません。

たとえば、最初の5つの画像は、BMW、ホンダ、フォード、アルファロメオ、および別のBMWです。ファイル名はすべて一意です-それらはすべて同じフォルダー内にあることに注意してください。したがって、この神話的なスクリプトを実行した後、BMWの2つの画像を含む4つのフォルダーができました。

すべてはShotwellでタグ付けされます。ほとんどがJPGであり、物事を複雑にするためにいくつかのPNGが挿入されています。複数のタグが存在する可能性がありますが、95%は単一のタグです。タグの保存場所はわかりませんが、タグは両方のコンピューターに表示されますが、メインのコンピューターにのみタグが付けられているため、各ファイルで想定しています。

さらなる調査により、タグが個々の画像の「キーワード」に対して保存されていることが示されているので、キーワードに基づいてディレクトリを作成する方法を尋ねる必要がありますか?

ここに行くと、とても学んでいます!

役立つ場合、これは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

それが私以外の誰にも理にかなっていると仮定すると、それは可能ですか?

1
Dave

exiftool を使用して、jpg、pngファイルからメタ情報を取得できます。 exiftoolをインストールするには、次を実行します。

$ Sudo apt-get install libimage-exiftool-Perl

使用法:exiftool -s example.jpg

最も完全な情報はTagsListとして保存されているようです。 Shotwellで保存された階層タグ(例:nature/sky)もサポートしています。タグは、SubjectKeywordsLastKeywordXMPフィールドにもあります。 SubjectKeywordsはタグ階層を保持しません。ネストされたタグのネストされたディレクトリを作成したくない場合は、それらを使用できます。

コマンドラインで指定された画像ファイルを対応するタグディレクトリに移動するpython3スクリプト(ハードリンクを作成し、元のファイル名を削除することにより)例:example.jpgにタグリストがある場合:naturenature/cloudsnature/mountainnature/skyの場合、結果のディレクトリツリーは次のようになります:

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

注:常に破壊的なコマンドを実行する前にデータをバックアップしてください(バグが発生します)

#!/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)

move-to-tag-dirs のどこかにある$PATHという名前のファイルに保存します。ファイルに実行権限があることを確認してください。

$ chmod +x move-to-tag-dirs

関連: .pyプログラムを直接実行する方法

次に、すべての画像を対応するタグディレクトリに移動するには、次を実行します。

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

'Argument list too long'エラーが発生した場合は、次を実行します。

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

「mv:引数リストが長すぎます」を参照してください?

エラー処理、階層タグのサポート、ファイル名、タグなどの異常な文字のサポートを無視すると、スクリプトを大幅に簡素化できます(この場合、単純な1回限りのシェルスクリプトで十分です)。

3
jfs

J. F. Sebastianの答えはおそらくあなたが探しているものですが、 tagsistant という名前のタグベースのファイルシステムもあります。タグを従来のファイルシステムのディレクトリのように扱い、ナビゲーションによってファイルを参照できます。これにより、ファイルに複数のタグがあり、それらのタグを検索およびソートする場合に簡単になります。

3
emk2203