Skip to content

Commit 522c218

Browse files
committed
Added --pattern to CLI, closes #30
1 parent 8ed104e commit 522c218

File tree

4 files changed

+95
-26
lines changed

4 files changed

+95
-26
lines changed

README.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ The command line tool can also be run via `python -m osxmetadata`. Running it w
3232

3333
```
3434
Usage: osxmetadata [OPTIONS] FILE
35-
Usage: __main__.py [OPTIONS] FILE
36-
35+
3736
Read/write metadata from file(s).
3837
3938
Options:
@@ -64,13 +63,25 @@ Options:
6463
tags' sets tags and keywords to same values.
6564
-B, --backup Backup FILE attributes. Backup file
6665
'.osxmetadata.json' will be created in same
67-
folder as FILE. Only backs up attributes
66+
folder as FILE. Only backs up attributes
6867
known to osxmetadata.
6968
-R, --restore Restore FILE attributes from backup file.
7069
Restore will look for backup file
7170
'.osxmetadata.json' in same folder as FILE.
7271
-V, --verbose Print verbose output.
7372
-f, --copyfrom SOURCE_FILE Copy attributes from file SOURCE_FILE.
73+
--files-only Do not apply metadata commands to
74+
directories themselves, only files in a
75+
directory.
76+
-p, --pattern PATTERN Only process files matching PATTERN; only
77+
applies to --walk. If specified, only files
78+
matching PATTERN will be processed as each
79+
directory is walked. May be used for than
80+
once to specify multiple patterns. For
81+
example, tag all *.pdf files in projectdir
82+
and subfolders with tag 'project':
83+
osxmetadata --append tags 'project' --walk
84+
projectdir/ --pattern '*.pdf'
7485
7586
Valid attributes for ATTRIBUTE: Each attribute has a short name, a constant
7687
name, and a long constant name. Any of these may be used for ATTRIBUTE

osxmetadata/__main__.py

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# /usr/bin/env python3
22

33
import datetime
4+
import glob
45
import itertools
56
import json
67
import logging
@@ -274,6 +275,18 @@ def get_help(self, ctx):
274275
default=False,
275276
required=False,
276277
)
278+
PATTERN_OPTION = click.option(
279+
"--pattern",
280+
"-p",
281+
metavar="PATTERN",
282+
help="Only process files matching PATTERN; only applies to --walk. "
283+
"If specified, only files matching PATTERN will be processed as each directory is walked. "
284+
"May be used for than once to specify multiple patterns. "
285+
"For example, tag all *.pdf files in projectdir and subfolders with tag 'project': "
286+
"osxmetadata --append tags 'project' --walk projectdir/ --pattern '*.pdf'",
287+
multiple=True,
288+
required=False,
289+
)
277290

278291

279292
@click.command(cls=MyClickCommand)
@@ -297,6 +310,7 @@ def get_help(self, ctx):
297310
@VERBOSE_OPTION
298311
@COPY_FROM_OPTION
299312
@FILES_ONLY_OPTION
313+
@PATTERN_OPTION
300314
@click.pass_context
301315
def cli(
302316
ctx,
@@ -319,6 +333,7 @@ def cli(
319333
verbose,
320334
copyfrom,
321335
files_only,
336+
pattern,
322337
):
323338
""" Read/write metadata from file(s). """
324339

@@ -403,30 +418,43 @@ def cli(
403418

404419
# loop through each file, process it, then do backup or restore if needed
405420
for filename in files:
406-
process_files(
407-
ctx,
408-
[filename],
409-
json_,
410-
set_,
411-
append,
412-
update,
413-
remove,
414-
clear,
415-
get,
416-
list_,
417-
mirror,
418-
wipe,
419-
verbose,
420-
copyfrom,
421-
backup,
422-
restore,
423-
walk,
424-
files_only,
425-
)
421+
if not all([os.path.isdir(filename), walk, pattern]):
422+
process_files(
423+
ctx,
424+
[filename],
425+
json_,
426+
set_,
427+
append,
428+
update,
429+
remove,
430+
clear,
431+
get,
432+
list_,
433+
mirror,
434+
wipe,
435+
verbose,
436+
copyfrom,
437+
backup,
438+
restore,
439+
walk,
440+
files_only,
441+
)
426442

427443
if walk and os.path.isdir(filename):
428444
for root, dirnames, filenames in os.walk(filename):
429-
filepaths = [os.path.join(root, fname) for fname in dirnames + filenames]
445+
if pattern:
446+
# only process files matching pattern
447+
filepaths = []
448+
for dirname in dirnames:
449+
for matches in [
450+
glob.glob(os.path.join(os.path.join(root, dirname), pat))
451+
for pat in pattern
452+
]:
453+
filepaths.extend(matches)
454+
else:
455+
filepaths = [
456+
os.path.join(root, fname) for fname in dirnames + filenames
457+
]
430458
process_files(
431459
ctx,
432460
filepaths,
@@ -481,7 +509,7 @@ def process_files(
481509
if verbose:
482510
click.echo(f"Skipping directory: {fpath}")
483511
continue
484-
512+
485513
if verbose:
486514
click.echo(f"Processing file: {fpath}")
487515

osxmetadata/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.99.8"
1+
__version__ = "0.99.9"

tests/test_cli.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,36 @@ def test_cli_walk_files_only(temp_dir):
843843
assert not md.tags
844844

845845

846+
def test_cli_walk_pattern(temp_dir):
847+
""" test --walk with --pattern """
848+
import os
849+
import pathlib
850+
from osxmetadata import OSXMetaData, Tag
851+
from osxmetadata.__main__ import cli
852+
853+
dirname = pathlib.Path(temp_dir)
854+
os.makedirs(dirname / "temp" / "subfolder1")
855+
os.makedirs(dirname / "temp" / "subfolder2")
856+
create_file(dirname / "temp" / "temp1.txt")
857+
create_file(dirname / "temp" / "subfolder1" / "sub1.txt")
858+
create_file(dirname / "temp" / "subfolder1" / "sub1.pdf")
859+
860+
runner = CliRunner()
861+
result = runner.invoke(
862+
cli, ["--set", "tags", "FOO", "--walk", "--pattern", "*.pdf", temp_dir]
863+
)
864+
assert result.exit_code == 0
865+
866+
md = OSXMetaData(dirname / "temp" / "subfolder1" / "sub1.pdf")
867+
assert md.tags == [Tag("FOO")]
868+
869+
md = OSXMetaData(dirname / "temp" / "subfolder1" / "sub1.txt")
870+
assert not md.tags
871+
872+
md = OSXMetaData(dirname / "temp" / "subfolder2")
873+
assert not md.tags
874+
875+
846876
def test_cli_files_only(temp_dir):
847877
""" test --files-only without --walk """
848878
import glob

0 commit comments

Comments
 (0)