BareGit

ffmagick: support processing directories.

Author: MetroWind <chris.corsair@gmail.com>
Date: Sun Nov 2 21:10:32 2025 -0800
Commit: c9170be038ebdf2afab1b7583e2eabb27000dab9

Changes

diff --git a/ffmagick/ffmagick.py b/ffmagick/ffmagick.py
index 794bb4d..3d28bbe 100644
--- a/ffmagick/ffmagick.py
+++ b/ffmagick/ffmagick.py
@@ -15,8 +15,7 @@ class ProgressBar:
 
     def next(self):
         self.current += 1
-        print("\r{} {}/{}".format(self.text, self.current, self.max), flush=True,
-              end="")
+        print(f"\r{self.text} {self.current}/{self.max}", flush=True, end="")
 
     def finish(self):
         print(flush=True)
@@ -47,8 +46,8 @@ class Profile:
                 return cls(p)
 
     def __str__(self):
-        return "{} ({}): {}\n{}".format(self.name, self.processor.name,
-                                        self.desc, self.command)
+        return f"{self.name} ({self.processor.name}): {self.desc}\n" \
+            f"{self.command}"
 
 def getConfigFiles():
     files = []
@@ -140,33 +139,54 @@ def runOnce(config, profile, input_file, output_dir):
         if not os.path.exists(output_dir):
             os.makedirs(output_dir)
     if profile.processor == Processor.FFMPEG:
-        cmd = "\"{}\" -y -i \"{}\" {} \"{}\"".format(
-            config.ffmpeg_bin, input_file, profile.command, output_file)
+        cmd = f"\"{config.ffmpeg_bin}\" -y -i \"{input_file}\"" \
+            f" {profile.command} \"{output_file}\""
     elif profile.processor == Processor.IMAGEMAGICK:
-        cmd = "\"{}\" \"{}\" {} \"{}\"".format(
-            config.imagemagick_bin, input_file, profile.command, output_file)
+        cmd = f"\"{config.imagemagick_bin}\" \"{input_file}\""\
+            f" {profile.command} \"{output_file}\""
     return subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                           text=True)
 
-def runAll(config, profile, input_files, output_dir):
+def runAll(config, profile, input_files, output_dir, ignore_error=False):
     bar = Progress("Processing", max=len(input_files))
+    failed = []
     for f in input_files:
         bar.next()
         result = runOnce(config, profile, f, output_dir)
         if result.returncode != 0:
+            failed.append(f)
+            if ignore_error:
+                continue
             bar.finish()
             print("ERROR: failed to process {}. Log:\n")
             print(result.stdout)
-            return False
+            return failed
     bar.finish()
-    return True
+    return failed
+
+# Return a list of files found in paths, which is a list of files or
+# directories. For each element in “paths”, if it is a file, add it to the
+# result; if it is a directory, add all the files (not recursively) in it to the
+# result.
+def getFilesFromPaths(paths):
+    files = []
+    for p in paths:
+        if os.path.isdir(p):
+            for entry in os.listdir(p):
+                f = os.path.join(p, entry)
+                if os.path.isfile(f):
+                    files.append(f)
+        else:
+            files.append(p)
+    return files
 
 def main():
     import argparse
     parser = argparse.ArgumentParser(
         prog='FFmagick', description='What the program does')
     parser.add_argument('files', metavar="FILE", nargs='*',
-                        help="File to process")
+                        help="File to process. If FILE is a directory, "
+                        "all files in it are processed (but not recursively).")
     parser.add_argument('-p', "--profile", metavar="PROFILE", dest="profile",
                         help="Specify the profile to process the files")
     parser.add_argument("-l", "--list-profiles", action="store_true",
@@ -200,11 +220,20 @@ def main():
     output_dir = None
     if "output_dir" in args:
         output_dir = args.output_dir
-    if not runAll(config, config.getProfile(args.profile), args.files,
-                output_dir):
-        return 1
 
-    return 0
+    input_files = getFilesFromPaths(args.files)
+    ignore_error = False
+    if len(input_files) > len(args.files):
+        ignore_error = True
+    failed = runAll(config, config.getProfile(args.profile), input_files,
+                    output_dir, ignore_error)
+    if failed:
+        print("Failed files:")
+        for f in failed:
+            print(f)
+        return 1
+    else:
+        return 0
 
 if __name__ == "__main__":
     sys.exit(main())