Skip to content

Commit 492d860

Browse files
norbertwgkmilos
authored andcommitted
replace using Exif tags after date/time
1 parent c8088b8 commit 492d860

File tree

2 files changed

+79
-41
lines changed

2 files changed

+79
-41
lines changed

app/actions.cpp

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1821,23 +1821,31 @@ 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+
const size_t max = 1024;
1825+
char basename[max] = {};
1826+
if (strftime(basename, max, format.c_str(), tm) == 0) {
1827+
std::cerr << _("Filename format yields empty filename for the file") << " " << path << "\n";
1828+
return 1;
1829+
}
1830+
1831+
newPath = (p.parent_path() / (basename + p.extension().string())).string();
1832+
18241833
// rename using exiv2 tags
1834+
// is done after calling setting date/time: the value retrieved from tag might include something like %Y, which then
1835+
// should not be replaced by year
18251836
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::regex format_regex(":{1}?(Exif\\..*?):{1}?");
1838+
#if defined(_WIN32)
18371839
std::string illegalChars = "\\/:*?\"<>|";
1838-
1839-
std::smatch base_match;
1840-
while (std::regex_search(format, base_match, format_regex)) {
1840+
#elif defined(__APPLE__)
1841+
std::string illegalChars = "/:";
1842+
#else
1843+
std::string illegalChars = "/";
1844+
#endif
1845+
std::regex_token_iterator<std::string::iterator> rend;
1846+
std::regex_token_iterator<std::string::iterator> token(format.begin(), format.end(), format_regex);
1847+
while (token != rend) {
1848+
std::string tag = token->str().substr(1, token->str().length() - 2);
18411849
if (image == 0) {
18421850
image = Exiv2::ImageFactory::open(path);
18431851
image->readMetadata();
@@ -1847,35 +1855,27 @@ int renameFile(std::string& newPath, const tm* tm) {
18471855
}
18481856
}
18491857
Exiv2::ExifData& exifData = image->exifData();
1850-
const auto key = exifData.findKey(Exiv2::ExifKey::ExifKey(base_match[2]));
1858+
const auto key = exifData.findKey(Exiv2::ExifKey::ExifKey(tag));
18511859
std::string val = "";
18521860
if (key != exifData.end()) {
18531861
val = key->print(&exifData);
18541862
if (val.length() == 0) {
1855-
std::cerr << _("Warning: ") << base_match[2] << _(" is empty.") << std::endl;
1863+
std::cerr << _("Warning: ") << tag << _(" is empty.") << std::endl;
18561864
} else {
1857-
// replace characters invalid in file name
1858-
for (std::string::iterator it = val.begin(); it < val.end(); ++it) {
1865+
// replace characters invalid in file name
1866+
for (std::string::iterator it = val.begin(); it < val.end(); ++it) {
18591867
bool found = illegalChars.find(*it) != std::string::npos;
18601868
if (found) {
18611869
*it = '_';
18621870
}
18631871
}
18641872
}
18651873
} else {
1866-
std::cerr << _("Warning: ") << base_match[2] << _(" is not included.") << std::endl;
1874+
std::cerr << _("Warning: ") << tag << _(" is not included.") << std::endl;
18671875
}
1868-
replace(format, base_match[1], val);
1869-
}
1870-
1871-
const size_t max = 1024;
1872-
char basename[max] = {};
1873-
if (strftime(basename, max, format.c_str(), tm) == 0) {
1874-
std::cerr << _("Filename format yields empty filename for the file") << " " << path << "\n";
1875-
return 1;
1876+
replace(newPath, *token++, val);
18761877
}
18771878

1878-
newPath = (p.parent_path() / (basename + p.extension().string())).string();
18791879
p = fs::path(newPath);
18801880

18811881
if (p.parent_path() == oldFsPath.parent_path() && p.filename() == oldFsPath.filename()) {

tests/bash_tests/test_rename.py

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22

3-
from system_tests import CaseMeta, CopyTmpFiles, DeleteFiles, path, FileDecoratorBase
3+
from system_tests import CaseMeta, CopyFiles, CopyTmpFiles, DeleteFiles, path, FileDecoratorBase
44

55
###########################################################
66
# rename with different formats
@@ -12,7 +12,7 @@
1212

1313
@CopyTmpFiles("$data_path/" + infile)
1414
@DeleteFiles("$tmp_path/" + outfile)
15-
class Rename1(metaclass=CaseMeta):
15+
class Rename_dbY(metaclass=CaseMeta):
1616
infilename = path("$tmp_path/" + infile)
1717
outfilename = path("$tmp_path/" + outfile)
1818
commands = [
@@ -34,7 +34,7 @@ class Rename1(metaclass=CaseMeta):
3434

3535
@CopyTmpFiles("$data_path/" + infile)
3636
@DeleteFiles("$tmp_path/" + outfile)
37-
class Rename2(metaclass=CaseMeta):
37+
class Rename_YmdHM(metaclass=CaseMeta):
3838
infilename = path("$tmp_path/" + infile)
3939
outfilename = path("$tmp_path/" + outfile)
4040
commands = [
@@ -56,7 +56,7 @@ class Rename2(metaclass=CaseMeta):
5656

5757
@CopyTmpFiles("$data_path/" + infile)
5858
@DeleteFiles("$tmp_path/" + outfile)
59-
class Rename3(metaclass=CaseMeta):
59+
class Rename_ExifTags(metaclass=CaseMeta):
6060
infilename = path("$tmp_path/" + infile)
6161
outfilename = path("$tmp_path/" + outfile)
6262
commands = [
@@ -78,7 +78,7 @@ class Rename3(metaclass=CaseMeta):
7878

7979
@CopyTmpFiles("$data_path/" + infile)
8080
@DeleteFiles("$tmp_path/" + outfile)
81-
class Rename4(metaclass=CaseMeta):
81+
class Rename_ExifTagsInvalidChar(metaclass=CaseMeta):
8282
infilename = path("$tmp_path/" + infile)
8383
outfilename = path("$tmp_path/" + outfile)
8484
commands = [
@@ -97,6 +97,36 @@ class Rename4(metaclass=CaseMeta):
9797
stderr = [""] * len(commands)
9898
retval = [0] * len(commands)
9999

100+
###########################################################
101+
# rename with keeping suffix
102+
###########################################################
103+
104+
basename ="_DSC8437"
105+
outfile = "02_Sep_2018.PANO.exv"
106+
renformat = "%d_%b_%Y:basesuffix:"
107+
108+
@CopyTmpFiles("$data_path/_DSC8437.exv")
109+
@DeleteFiles("$tmp_path/" + outfile)
110+
class Rename_basesuffix(metaclass=CaseMeta):
111+
infilename1 = path("$tmp_path/" + basename + ".exv")
112+
infilename2 = path("$tmp_path/" + basename + ".PANO.exv")
113+
outfilename = path("$tmp_path/" + outfile)
114+
commands = [
115+
# first command to prepare a file name with suffix
116+
"$exiv2 --verbose --rename :basename:.PANO " + infilename1,
117+
"$exiv2 --verbose --rename " + renformat + " " + infilename2
118+
]
119+
stdout = [
120+
"""File 1/1: $infilename1
121+
Renaming file to $infilename2
122+
""",
123+
"""File 1/1: $infilename2
124+
Renaming file to $outfilename
125+
"""
126+
]
127+
stderr = [""] * len(commands)
128+
retval = [0] * len(commands)
129+
100130
###########################################################
101131
# rename error: tag is not included
102132
###########################################################
@@ -107,7 +137,7 @@ class Rename4(metaclass=CaseMeta):
107137

108138
@CopyTmpFiles("$data_path/" + infile)
109139
@DeleteFiles("$tmp_path/" + outfile)
110-
class RenameError1(metaclass=CaseMeta):
140+
class Rename_TagNotIncluded(metaclass=CaseMeta):
111141
infilename = path("$tmp_path/" + infile)
112142
outfilename = path("$tmp_path/" + outfile)
113143
commands = [
@@ -123,27 +153,35 @@ class RenameError1(metaclass=CaseMeta):
123153
retval = [0] * len(commands)
124154

125155
###########################################################
126-
# rename error: unbalanced colon
156+
# rename error: file contains no Exif data
127157
###########################################################
128158

129159
infile ="_DSC8437.exv"
130160
outfile = "_DSC8437_.exv"
131-
renformat = ":basename:_Exif.Image.ImageDescription:"
161+
renformat = ":basename:_:Exif.Image.ImageDescription:"
132162

133163
@CopyTmpFiles("$data_path/" + infile)
134-
@DeleteFiles("$tmp_path/" + outfile)
135-
class RenameError2(metaclass=CaseMeta):
164+
#@DeleteFiles("$tmp_path/" + outfile)
165+
class Rename_NoExifData(metaclass=CaseMeta):
136166
infilename = path("$tmp_path/" + infile)
137167
outfilename = path("$tmp_path/" + outfile)
138168
commands = [
169+
"$exiv2 --delete a " + infilename,
139170
"$exiv2 --verbose --rename " + renformat + " " + infilename
140171
]
141172
stdout = [
173+
"",
142174
"""File 1/1: $infilename
143-
Renaming file to $outfilename
144175
"""
145176
]
146-
stderr = ["""Warning: Exif.Image.ImageDescription is not included.
177+
stderr = ["",
178+
"""$infilename: No Exif data found in the file
147179
"""]
148-
retval = [0] * len(commands)
180+
retval = [0, 253]
181+
182+
# ###########################################################
183+
# # rename error: unbalanced colon
184+
# ###########################################################
185+
186+
149187

0 commit comments

Comments
 (0)