[pp:exec] use non-UNC path replacements (#8879)

provide '{_path_unc}' and '{_directory_unc}' replacement fields
This commit is contained in:
Mike Fährmann
2026-02-14 11:25:08 +01:00
parent d99c8c1320
commit 98eb857794
4 changed files with 32 additions and 19 deletions

View File

@@ -216,8 +216,10 @@
'vp8', 'vp9', 'vp9-lossless', 'copy', 'zip'. 'vp8', 'vp9', 'vp9-lossless', 'copy', 'zip'.
--exec CMD Execute CMD for each downloaded file. Supported --exec CMD Execute CMD for each downloaded file. Supported
replacement fields are {} or {_path}, replacement fields are {} or {_path},
{_directory}, {_filename}. Example: --exec {_temppath}, {_directory}, {_filename}. On
"convert {} {}.png && rm {}" Windows, use {_path_unc} or {_directory_unc}
for UNC paths. Example: --exec "convert {}
{}.png && rm {}"
--exec-after CMD Execute CMD after all files were downloaded. --exec-after CMD Execute CMD after all files were downloaded.
Example: --exec-after "cd {_directory} && Example: --exec-after "cd {_directory} &&
convert * ../doc.pdf" convert * ../doc.pdf"

View File

@@ -899,7 +899,8 @@ def build_parser():
action=AppendCommandAction, const={"name": "exec"}, action=AppendCommandAction, const={"name": "exec"},
help=("Execute CMD for each downloaded file. " help=("Execute CMD for each downloaded file. "
"Supported replacement fields are " "Supported replacement fields are "
"{} or {_path}, {_directory}, {_filename}. " "{} or {_path}, {_temppath}, {_directory}, {_filename}. "
"On Windows, use {_path_unc} or {_directory_unc} for UNC paths. "
"Example: --exec \"convert {} {}.png && rm {}\""), "Example: --exec \"convert {} {}.png && rm {}\""),
) )
postprocessor.add_argument( postprocessor.add_argument(

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2018-2023 Mike Fährmann # Copyright 2018-2026 Mike Fährmann
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
@@ -61,7 +61,8 @@ class ExecPP(PostProcessor):
def _prepare_cmd(self, cmd): def _prepare_cmd(self, cmd):
if isinstance(cmd, str): if isinstance(cmd, str):
self._sub = util.re( self._sub = util.re(
r"\{(_directory|_filename|_(?:temp)?path|)\}").sub r"(?i)\{(_directory(?:_unc)?|_filename"
r"|_(?:temp)?path(?:_unc)?|)\}").sub
return self.exec_string, cmd return self.exec_string, cmd
else: else:
return self.exec_list, [formatter.parse(arg) for arg in cmd] return self.exec_list, [formatter.parse(arg) for arg in cmd]
@@ -73,10 +74,13 @@ class ExecPP(PostProcessor):
if archive and archive.check(kwdict): if archive and archive.check(kwdict):
return return
kwdict["_directory"] = pathfmt.realdirectory kwdict["_directory"] = pathfmt.directory
kwdict["_filename"] = pathfmt.filename kwdict["_filename"] = pathfmt.filename
kwdict["_temppath"] = pathfmt.temppath kwdict["_temppath"] = pathfmt.temppath
kwdict["_path"] = pathfmt.realpath kwdict["_path"] = pathfmt.path
if util.WINDOWS:
kwdict["_directory_unc"] = pathfmt.realdirectory
kwdict["_path_unc"] = pathfmt.realpath
args = [arg.format_map(kwdict) for arg in self.args] args = [arg.format_map(kwdict) for arg in self.args]
args[0] = os.path.expanduser(args[0]) args[0] = os.path.expanduser(args[0])
@@ -133,14 +137,17 @@ class ExecPP(PostProcessor):
) )
def _replace(self, match): def _replace(self, match):
name = match[1] attr = {
if name == "_directory": "" : "path",
return quote(self.pathfmt.realdirectory) "_path" : "path",
if name == "_filename": "_path_unc" : "realpath",
return quote(self.pathfmt.filename) "_temppath" : "temppath",
if name == "_temppath": "_temppath_unc" : "temppath",
return quote(self.pathfmt.temppath) "_directory" : "directory",
return quote(self.pathfmt.realpath) "_directory_unc": "realdirectory",
"_filename" : "filename",
}[match[1].lower()]
return quote(getattr(self.pathfmt, attr))
__postprocessor__ = ExecPP __postprocessor__ = ExecPP

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2019-2025 Mike Fährmann # Copyright 2019-2026 Mike Fährmann
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
@@ -196,7 +196,8 @@ class ExecTest(BasePostprocessorTest):
def test_command_string(self): def test_command_string(self):
self._create({ self._create({
"command": "echo {} {_path} {_temppath} {_directory} {_filename} " "command": "echo {} {_path} {_path_unc} {_temppath} "
"{_directory} {_directory_unc} {_filename} "
"&& rm {};", "&& rm {};",
}) })
@@ -208,12 +209,14 @@ class ExecTest(BasePostprocessorTest):
p.assert_called_once_with( p.assert_called_once_with(
(f"echo " (f"echo "
f"{self.pathfmt.realpath} " f"{self.pathfmt.path} "
f"{self.pathfmt.path} "
f"{self.pathfmt.realpath} " f"{self.pathfmt.realpath} "
f"{self.pathfmt.temppath} " f"{self.pathfmt.temppath} "
f"{self.pathfmt.directory} "
f"{self.pathfmt.realdirectory} " f"{self.pathfmt.realdirectory} "
f"{self.pathfmt.filename} " f"{self.pathfmt.filename} "
f"&& rm {self.pathfmt.realpath};"), f"&& rm {self.pathfmt.path};"),
shell=True, shell=True,
creationflags=0, creationflags=0,
start_new_session=False, start_new_session=False,