@@ -47,13 +47,15 @@ def __str__(self):
47
47
help = "Enables verbose mode. Disabled by default" ,
48
48
default = False ,
49
49
)
50
+ @click .option ("--format-pattern" , help = 'Pattern template. e.g. %Y/%m/{file}' , required = False )
51
+ @click .option ("--unknown-format-pattern" , help = 'Pattern template fallback when date cannot get extracted' , required = False )
50
52
@click .option (
51
53
"--interactive/--no-interactive" ,
52
54
help = "Disables confirmation prompts. Enabled by default" ,
53
55
default = True ,
54
56
)
55
57
@click .pass_context
56
- def cli (ctx , verbose , interactive ):
58
+ def cli (ctx , verbose , interactive , format_pattern , unknown_format_pattern ):
57
59
"""
58
60
Command line interface.
59
61
@@ -62,7 +64,7 @@ def cli(ctx, verbose, interactive):
62
64
file arguments accept file names and a special value "-" to indicate stdin or stdout
63
65
"""
64
66
if not ctx .obj :
65
- global_settings = GlobalSettings ()
67
+ global_settings = GlobalSettings (format_pattern = format_pattern , unknown_format_pattern = unknown_format_pattern )
66
68
ctx .obj = Context (
67
69
global_settings = global_settings ,
68
70
storage = Storage (path = global_settings .storage_location ),
@@ -110,8 +112,12 @@ def inspect(ctx: Context, src, media_only):
110
112
print_table_summary (name = name , files = files , duplicated_files = duplicated_files )
111
113
112
114
if duplicated_files :
115
+ duplicated_list_of_files_sorted_by_name_length = list (
116
+ sorted (duplicated_list , key = lambda file : (len (file .path .name ), len (str (file .path ))))
117
+ for duplicated_list in duplicated_files
118
+ )
113
119
print_duplicate_files (
114
- duplicated_files = duplicated_files , from_path = directory .path
120
+ duplicated_files = duplicated_list_of_files_sorted_by_name_length , from_path = directory .path
115
121
)
116
122
117
123
if isinstance (directory , Catalogue ):
@@ -143,8 +149,10 @@ def delete_catalogue(ctx: Context, name):
143
149
@cli .command ()
144
150
@click .argument ("name" )
145
151
@click .argument ("src" , required = False )
152
+ @click .option ("--format-pattern" , help = 'Pattern template. e.g. %Y/%m/{file}' , required = False )
153
+ @click .option ("--unknown-format-pattern" , help = 'Pattern template fallback when date cannot get extracted' , required = False )
146
154
@click .pass_obj
147
- def create_catalogue (ctx : Context , name , src ):
155
+ def create_catalogue (ctx : Context , name , src , format_pattern , unknown_format_pattern ):
148
156
"""
149
157
Creates a new catalogue.
150
158
"""
@@ -155,6 +163,13 @@ def create_catalogue(ctx: Context, name, src):
155
163
if not src_path or not src_path .is_dir ():
156
164
raise click .BadParameter (f'Error "{ src } " is not an existing path' )
157
165
166
+ format_pattern = format_pattern or ctx .global_settings .format_pattern
167
+ unknown_format_pattern = unknown_format_pattern or ctx .global_settings .unknown_format_pattern
168
+ if not format_pattern :
169
+ raise click .BadParameter (
170
+ 'Error there is no format pattern specified'
171
+ )
172
+
158
173
catalogue_path = src_path or ctx .workdir
159
174
existing_catalogue = ctx .storage .load_catalogue (name )
160
175
@@ -165,8 +180,8 @@ def create_catalogue(ctx: Context, name, src):
165
180
166
181
new_catalogue = Catalogue (
167
182
name = name ,
168
- format_pattern = ctx . global_settings . format_pattern ,
169
- unknown_format_pattern = ctx . global_settings . unknown_format_pattern ,
183
+ format_pattern = format_pattern ,
184
+ unknown_format_pattern = unknown_format_pattern ,
170
185
path = catalogue_path ,
171
186
)
172
187
new_catalogue .explore ()
@@ -261,7 +276,7 @@ def extract_files(src_data):
261
276
262
277
if duplicated_list_of_files :
263
278
duplicated_list_of_files_sorted_by_name_length = list (
264
- sorted (duplicated_list , key = lambda file : len (file .path .name ))
279
+ sorted (duplicated_list , key = lambda file : ( len (file .path .name ), len ( str ( file . path )) ))
265
280
for duplicated_list in duplicated_list_of_files
266
281
)
267
282
@@ -325,16 +340,29 @@ def operate(ctx, src, dst, operation_mode, dry_run=False):
325
340
f'Error "{ dst } " is neither a catalogue or an existing directory'
326
341
)
327
342
328
- if isinstance (src_data , File ) and (
329
- not dst_data or not isinstance (dst_data , (Catalogue , Directory ))
330
- ):
343
+ if isinstance (src_data , (Catalogue , Directory )) and dst_data :
344
+ if src_data .path .is_relative_to (dst_data .path ):
345
+ raise click .BadParameter (
346
+ f'Error "{ dst } " cannot be a subdirectory of { src } '
347
+ )
348
+
349
+ if operation_mode in (Operation .MOVE , Operation .COPY ):
350
+ format_pattern = ctx .global_settings .format_pattern
351
+ if dst_data and isinstance (dst_data , Catalogue ):
352
+ format_pattern = format_pattern or dst_data .format_pattern
353
+ if not format_pattern :
354
+ raise click .BadParameter (
355
+ 'Error there is no format pattern specified'
356
+ )
357
+
358
+ if isinstance (src_data , File ) and not dst_data :
331
359
raise click .BadParameter (
332
360
f'Error "{ src } " is a file but no valid destination was provided'
333
361
)
334
362
335
363
with console .status (
336
364
f"[green]Inspecting files..." ,
337
- ) as status :
365
+ ):
338
366
(
339
367
duplicated_list_of_files_sorted_by_name_length ,
340
368
duplicated_discarded_files ,
@@ -447,8 +475,8 @@ def process_files(
447
475
path_format = ctx .global_settings .format_pattern
448
476
unknown_format_pattern = ctx .global_settings .unknown_format_pattern
449
477
if isinstance (dst_data , Catalogue ):
450
- path_format = dst_data .format_pattern
451
- unknown_format_pattern = dst_data .unknown_format_pattern
478
+ path_format = path_format or dst_data .format_pattern
479
+ unknown_format_pattern = unknown_format_pattern or dst_data .unknown_format_pattern
452
480
453
481
tree = DirectoryTree ()
454
482
skipped_tree = DirectoryTree ()
0 commit comments