diff --git a/picard/file.py b/picard/file.py
index 1fe4eeebdf..6d49ccd6cd 100644
--- a/picard/file.py
+++ b/picard/file.py
@@ -676,8 +676,16 @@ def _rename(self, old_filename, metadata, settings):
new_dirname = os.path.dirname(new_filename)
if not os.path.isdir(new_dirname):
os.makedirs(new_dirname)
- if not settings['move_overwrite_existing_files']:
- new_filename = get_available_filename(new_filename, old_filename)
+ config = get_config()
+ strategy = config.setting.get('move_conflict_strategy', 'rename')
+ if os.path.exists(new_filename):
+ if strategy == "skip":
+ log.warning("Destination exists, skipping move of %r", old_filename)
+ return old_filename
+ elif strategy == "rename":
+ new_filename = get_available_filename(new_filename, old_filename)
+ elif strategy == "overwrite":
+ pass
log.debug("Moving file %r => %r", old_filename, new_filename)
move_ensure_casing(old_filename, new_filename)
return new_filename
@@ -708,7 +716,7 @@ def _move_additional_files(self, old_filename, new_filename, config):
patterns = self._compile_move_additional_files_pattern(patterns_string)
try:
moves = self._get_additional_files_moves(old_path, new_path, patterns)
- self._apply_additional_files_moves(moves, config.setting['move_overwrite_existing_files'])
+ self._apply_additional_files_moves(moves)
except OSError as why:
log.error("Failed to scan %r: %s", old_path, why)
@@ -732,15 +740,22 @@ def _get_additional_files_moves(self, old_path, new_path, patterns):
yield (entry.path, new_file_path)
break # we are done with this file
- def _apply_additional_files_moves(self, moves, overwrite_existing_files=False):
+ def _apply_additional_files_moves(self, moves):
+ config = get_config()
+ strategy = config.setting.get('move_conflict_strategy', 'rename')
for old_file_path, new_file_path in moves:
# FIXME we shouldn't do this from a thread!
if self.tagger.files.get(decode_filename(old_file_path)):
log.debug("File loaded in the tagger, not moving %r", old_file_path)
continue
- if not overwrite_existing_files and os.path.exists(new_file_path):
- log.warning("File %r already exists, not moving %r", new_file_path, old_file_path)
- continue
+ if os.path.exists(new_file_path):
+ if strategy == "skip":
+ log.warning("File %r exists, skipping %r", new_file_path, old_file_path)
+ continue
+ elif strategy == "rename":
+ new_file_path = get_available_filename(new_file_path)
+ elif strategy == "overwrite":
+ pass
log.debug("Moving %r to %r", old_file_path, new_file_path)
try:
shutil.move(old_file_path, new_file_path)
diff --git a/picard/options.py b/picard/options.py
index 3ecc63780d..1ceb2b517f 100644
--- a/picard/options.py
+++ b/picard/options.py
@@ -427,7 +427,6 @@ def make_default_toolbar_layout():
TextOption('setting', 'move_additional_files_pattern', "*.jpg *.png", title=N_("Additional file patterns"))
BoolOption('setting', 'move_files', False, title=N_("Move files"))
TextOption('setting', 'move_files_to', DEFAULT_MUSIC_DIR, title=N_("Destination directory"))
-BoolOption('setting', 'move_overwrite_existing_files', False, title=N_("Overwrite existing files"))
BoolOption('setting', 'rename_files', False, title=N_("Rename files"))
# picard/ui/options/renaming_compat.py
@@ -540,6 +539,7 @@ def make_default_toolbar_layout():
'',
title=N_("Sessions directory"),
)
+TextOption('setting', 'move_conflict_strategy', 'rename', title=N_("File conflict handling strategy"))
# picard/ui/searchdialog/album.py
#
diff --git a/picard/ui/options/renaming.py b/picard/ui/options/renaming.py
index fdd882d84b..0d711da4fa 100644
--- a/picard/ui/options/renaming.py
+++ b/picard/ui/options/renaming.py
@@ -75,9 +75,9 @@ class RenamingOptionsPage(OptionsPage):
OPTIONS = (
('move_files', ['move_files']),
('move_files_to', ['move_files_to']),
- ('move_overwrite_existing_files', ['move_overwrite_existing_files']),
('move_additional_files', ['move_additional_files']),
('move_additional_files_pattern', ['move_additional_files_pattern']),
+ ('move_conflict_strategy', ['move_conflict_strategy']),
('delete_empty_dirs', ['delete_empty_dirs']),
('rename_files', ['rename_files']),
('selected_file_naming_script_id', ['naming_script_selector']),
@@ -250,8 +250,11 @@ def load(self):
self.ui.move_files_to.setCursorPosition(0)
self.ui.move_additional_files.setChecked(config.setting['move_additional_files'])
self.ui.move_additional_files_pattern.setText(config.setting['move_additional_files_pattern'])
+ strategy = config.setting['move_conflict_strategy']
+ self.ui.move_conflict_skip.setChecked(strategy == "skip")
+ self.ui.move_conflict_rename.setChecked(strategy == "rename")
+ self.ui.move_conflict_overwrite.setChecked(strategy == "overwrite")
self.ui.delete_empty_dirs.setChecked(config.setting['delete_empty_dirs'])
- self.ui.move_overwrite_existing_files.setChecked(config.setting['move_overwrite_existing_files'])
self.naming_scripts = config.setting['file_renaming_scripts']
self.selected_naming_script_id = config.setting['selected_file_naming_script_id']
if self.script_editor_dialog:
@@ -285,9 +288,14 @@ def save(self):
config.setting['move_files'] = self.ui.move_files.isChecked()
config.setting['move_files_to'] = os.path.normpath(self.ui.move_files_to.text())
config.setting['move_additional_files'] = self.ui.move_additional_files.isChecked()
+ if self.ui.move_conflict_skip.isChecked():
+ config.setting['move_conflict_strategy'] = "skip"
+ elif self.ui.move_conflict_rename.isChecked():
+ config.setting['move_conflict_strategy'] = "rename"
+ elif self.ui.move_conflict_overwrite.isChecked():
+ config.setting['move_conflict_strategy'] = "overwrite"
config.setting['move_additional_files_pattern'] = self.ui.move_additional_files_pattern.text()
config.setting['delete_empty_dirs'] = self.ui.delete_empty_dirs.isChecked()
- config.setting['move_overwrite_existing_files'] = self.ui.move_overwrite_existing_files.isChecked()
config.setting['selected_file_naming_script_id'] = self.selected_naming_script_id
def display_error(self, error):
diff --git a/ui/options_renaming.ui b/ui/options_renaming.ui
index 77af9be57a..664d05d0ae 100644
--- a/ui/options_renaming.ui
+++ b/ui/options_renaming.ui
@@ -80,9 +80,23 @@
-
-
+
- Overwrite existing files
+ Do not move duplicate files
+
+
+
+ -
+
+
+ Move and rename file with numeric suffix
+
+
+
+ -
+
+
+ Move and overwrite existing files
@@ -298,7 +312,9 @@
move_additional_files
move_additional_files_pattern
delete_empty_dirs
- move_overwrite_existing_files
+ move_conflict_skip
+ move_conflict_rename
+ move_conflict_overwrite
rename_files
naming_script_selector
open_script_editor