Skip to content

Commit c8088b8

Browse files
norbertwgkmilos
authored andcommitted
reanme files using Exif tags
1 parent 78557b6 commit c8088b8

File tree

2 files changed

+196
-0
lines changed

2 files changed

+196
-0
lines changed

app/actions.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1821,6 +1821,53 @@ int renameFile(std::string& newPath, const tm* tm) {
18211821
replace(format, ":dirname:", p.parent_path().filename().string());
18221822
replace(format, ":parentname:", p.parent_path().parent_path().filename().string());
18231823

1824+
// rename using exiv2 tags
1825+
Exiv2::Image::UniquePtr image;
1826+
std::regex format_regex(
1827+
// anything at the start
1828+
".*?"
1829+
// start of tag name after colon
1830+
"(:("
1831+
// tag name
1832+
".*?"
1833+
// end of tag name before colon
1834+
"):)"
1835+
// anything at the end
1836+
".*?");
1837+
std::string illegalChars = "\\/:*?\"<>|";
1838+
1839+
std::smatch base_match;
1840+
while (std::regex_search(format, base_match, format_regex)) {
1841+
if (image == 0) {
1842+
image = Exiv2::ImageFactory::open(path);
1843+
image->readMetadata();
1844+
if (image->exifData().empty()) {
1845+
std::string error("No Exif data found in file");
1846+
throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, error);
1847+
}
1848+
}
1849+
Exiv2::ExifData& exifData = image->exifData();
1850+
const auto key = exifData.findKey(Exiv2::ExifKey::ExifKey(base_match[2]));
1851+
std::string val = "";
1852+
if (key != exifData.end()) {
1853+
val = key->print(&exifData);
1854+
if (val.length() == 0) {
1855+
std::cerr << _("Warning: ") << base_match[2] << _(" is empty.") << std::endl;
1856+
} else {
1857+
// replace characters invalid in file name
1858+
for (std::string::iterator it = val.begin(); it < val.end(); ++it) {
1859+
bool found = illegalChars.find(*it) != std::string::npos;
1860+
if (found) {
1861+
*it = '_';
1862+
}
1863+
}
1864+
}
1865+
} else {
1866+
std::cerr << _("Warning: ") << base_match[2] << _(" is not included.") << std::endl;
1867+
}
1868+
replace(format, base_match[1], val);
1869+
}
1870+
18241871
const size_t max = 1024;
18251872
char basename[max] = {};
18261873
if (strftime(basename, max, format.c_str(), tm) == 0) {

tests/bash_tests/test_rename.py

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from system_tests import CaseMeta, CopyTmpFiles, DeleteFiles, path, FileDecoratorBase
4+
5+
###########################################################
6+
# rename with different formats
7+
###########################################################
8+
9+
infile ="_DSC8437.exv"
10+
outfile = "_DSC8437_02_Sep_2018.exv"
11+
renformat = ":basename:_%d_%b_%Y"
12+
13+
@CopyTmpFiles("$data_path/" + infile)
14+
@DeleteFiles("$tmp_path/" + outfile)
15+
class Rename1(metaclass=CaseMeta):
16+
infilename = path("$tmp_path/" + infile)
17+
outfilename = path("$tmp_path/" + outfile)
18+
commands = [
19+
"$exiv2 --verbose --rename " + renformat + " " + infilename
20+
]
21+
stdout = [
22+
"""File 1/1: $infilename
23+
Renaming file to $outfilename
24+
"""
25+
]
26+
stderr = [""] * len(commands)
27+
retval = [0] * len(commands)
28+
29+
###########################################################
30+
31+
infile ="_DSC8437.exv"
32+
outfile = "_DSC8437_2018-09-02-19-40.exv"
33+
renformat = ":basename:_%Y-%m-%d-%H-%M"
34+
35+
@CopyTmpFiles("$data_path/" + infile)
36+
@DeleteFiles("$tmp_path/" + outfile)
37+
class Rename2(metaclass=CaseMeta):
38+
infilename = path("$tmp_path/" + infile)
39+
outfilename = path("$tmp_path/" + outfile)
40+
commands = [
41+
"$exiv2 --verbose --rename " + renformat + " " + infilename
42+
]
43+
stdout = [
44+
"""File 1/1: $infilename
45+
Renaming file to $outfilename
46+
"""
47+
]
48+
stderr = [""] * len(commands)
49+
retval = [0] * len(commands)
50+
51+
###########################################################
52+
53+
infile ="_DSC8437.exv"
54+
outfile = "_DSC8437_NIKON D850_46.0 mm.exv"
55+
renformat = ":basename:_:Exif.Image.Model:_:Exif.Photo.FocalLengthIn35mmFilm:"
56+
57+
@CopyTmpFiles("$data_path/" + infile)
58+
@DeleteFiles("$tmp_path/" + outfile)
59+
class Rename3(metaclass=CaseMeta):
60+
infilename = path("$tmp_path/" + infile)
61+
outfilename = path("$tmp_path/" + outfile)
62+
commands = [
63+
"$exiv2 --verbose --rename " + renformat + " " + infilename
64+
]
65+
stdout = [
66+
"""File 1/1: $infilename
67+
Renaming file to $outfilename
68+
"""
69+
]
70+
stderr = [""] * len(commands)
71+
retval = [0] * len(commands)
72+
73+
###########################################################
74+
75+
infile ="_DSC8437.exv"
76+
outfile = "_DSC8437_a_b_c_d_e_f_g_h_i.exv"
77+
renformat = ":basename:_:Exif.Image.ImageDescription:"
78+
79+
@CopyTmpFiles("$data_path/" + infile)
80+
@DeleteFiles("$tmp_path/" + outfile)
81+
class Rename4(metaclass=CaseMeta):
82+
infilename = path("$tmp_path/" + infile)
83+
outfilename = path("$tmp_path/" + outfile)
84+
commands = [
85+
"""$exiv2 -M"set Exif.Image.ImageDescription Ascii a\\b/c:d*e?f<g>h|i" $infilename""",
86+
"$exiv2 --grep Exif.Image.ImageDescription $infilename",
87+
"$exiv2 --verbose --rename " + renformat + " " + infilename
88+
]
89+
stdout = [
90+
"",
91+
"""Exif.Image.ImageDescription Ascii 18 a\\b/c:d*e?f<g>h|i
92+
""",
93+
"""File 1/1: $infilename
94+
Renaming file to $outfilename
95+
"""
96+
]
97+
stderr = [""] * len(commands)
98+
retval = [0] * len(commands)
99+
100+
###########################################################
101+
# rename error: tag is not included
102+
###########################################################
103+
104+
infile ="_DSC8437.exv"
105+
outfile = "_DSC8437_.exv"
106+
renformat = ":basename:_:Exif.Image.ImageDescription:"
107+
108+
@CopyTmpFiles("$data_path/" + infile)
109+
@DeleteFiles("$tmp_path/" + outfile)
110+
class RenameError1(metaclass=CaseMeta):
111+
infilename = path("$tmp_path/" + infile)
112+
outfilename = path("$tmp_path/" + outfile)
113+
commands = [
114+
"$exiv2 --verbose --rename " + renformat + " " + infilename
115+
]
116+
stdout = [
117+
"""File 1/1: $infilename
118+
Renaming file to $outfilename
119+
"""
120+
]
121+
stderr = ["""Warning: Exif.Image.ImageDescription is not included.
122+
"""]
123+
retval = [0] * len(commands)
124+
125+
###########################################################
126+
# rename error: unbalanced colon
127+
###########################################################
128+
129+
infile ="_DSC8437.exv"
130+
outfile = "_DSC8437_.exv"
131+
renformat = ":basename:_Exif.Image.ImageDescription:"
132+
133+
@CopyTmpFiles("$data_path/" + infile)
134+
@DeleteFiles("$tmp_path/" + outfile)
135+
class RenameError2(metaclass=CaseMeta):
136+
infilename = path("$tmp_path/" + infile)
137+
outfilename = path("$tmp_path/" + outfile)
138+
commands = [
139+
"$exiv2 --verbose --rename " + renformat + " " + infilename
140+
]
141+
stdout = [
142+
"""File 1/1: $infilename
143+
Renaming file to $outfilename
144+
"""
145+
]
146+
stderr = ["""Warning: Exif.Image.ImageDescription is not included.
147+
"""]
148+
retval = [0] * len(commands)
149+

0 commit comments

Comments
 (0)