{"id":1402,"date":"2025-08-05T08:56:12","date_gmt":"2025-08-05T13:56:12","guid":{"rendered":"https:\/\/ma.rcbla.se\/blog\/?p=1402"},"modified":"2025-08-25T10:09:39","modified_gmt":"2025-08-25T15:09:39","slug":"convert-directory-of-images-on-the-command-line","status":"publish","type":"post","link":"https:\/\/ma.rcbla.se\/blog\/2025\/08\/convert-directory-of-images-on-the-command-line\/","title":{"rendered":"Convert directory of images on the command line"},"content":{"rendered":"<p>I had a need, well I always have a need but I finally got around to figuring this out, to resize a directory of images. I finally broke up with Adobe and had historically used the Photoshop batch functionality which was always wonky at best so that&#8217;s no longer possible. I&#8217;ve done some digging and discovered yet again that Linux just does everything better. So without further adieu the command:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">$ mogrify -path .\/webp_images\/ -format webp -quality 80 -resize 1200x1200\\&gt; *.jpg<\/pre>\n<p>Everything here is straightforward aside from the &#8216;\\>&#8217; after the resize flag. This extra bit prevents smaller images from being upscaled. FYI, you&#8217;ll need imagemagick installed to run the mogrify command. <\/p>\n<p>Extra credit, here&#8217;s a command to mogrify a directory of images no matter the file type:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nfor img in *.{jpg,jpeg,png,bmp}; do\r\n  &#x5B; -e &quot;$img&quot; ] &amp;&amp; mogrify -path .\/webp_images\/ -format webp -quality 80 -resize 1200x1200\\&gt; &quot;$img&quot;\r\ndone\r\n<\/pre>\n<p>UPDATE:<\/p>\n<p>Here&#8217;s another example that will loop over a directory recursively and resize without upscaling and save as WEBP.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nfind . -maxdepth 1 -type f \\( -iname '*.jpg' -o -iname '*.png' -o -iname '*.jpeg' -o -iname '*.bmp' \\) -exec mogrify -path .\/webp_images\/ -format webp -quality 80 -resize 1200x1200\\&gt; {} +\r\n<\/pre>\n<p>UPDATE 2:<\/p>\n<p>Here&#8217;s another example, a shell script, that will loop over a directory, save as WEBP and change the file name to include the directory that the image was found in.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\n#!\/bin\/bash\r\n\r\n# --- Configuration ---\r\n# Set the base directory to search for images. &quot;.&quot; means the current directory.\r\nSOURCE_DIR=&quot;.&quot;\r\n\r\n# Set the directory where processed images will be saved.\r\n# The ~ will be expanded to your home directory.\r\nOUTPUT_DIR=~\/web_images\r\n# ---------------------\r\n\r\n# Create the output directory if it doesn't already exist.\r\n# The '-p' flag prevents errors if the directory is already there.\r\necho &quot;Ensuring output directory exists at $OUTPUT_DIR...&quot;\r\nmkdir -p &quot;$OUTPUT_DIR&quot;\r\n\r\n# Use 'find' to locate all image files recursively and process them.\r\necho &quot;Starting image processing...&quot;\r\nfind &quot;$SOURCE_DIR&quot; -type f \\( -iname &quot;*.jpg&quot; -o -iname &quot;*.jpeg&quot; -o -iname &quot;*.png&quot; -o -iname &quot;*.bmp&quot; \\) -exec bash -c '\r\n  # This inline script is executed for each file found by `find`.\r\n  # The full path of the found file (e.g., .\/subdir\/image.jpg) is passed as the first argument ($1).\r\n  # The destination directory is passed as the second argument ($2).\r\n  file=&quot;$1&quot;\r\n  output_dir=&quot;$2&quot;\r\n\r\n  # 1. Get the parent directory name (e.g., &quot;subdir&quot;).\r\n  parent_dir=$(basename &quot;$(dirname &quot;$file&quot;)&quot;)\r\n\r\n  # 2. Get the filename without its original extension (e.g., &quot;image&quot;).\r\n  base_name_no_ext=$(basename &quot;${file%.*}&quot;)\r\n\r\n  # 3. Construct the new filename by prepending the parent directory name.\r\n  #    If the image is in the source directory itself (parent is &quot;.&quot;), we dont prepend &quot;.-&quot;.\r\n  if &#x5B; &quot;$parent_dir&quot; = &quot;.&quot; ] || &#x5B; &quot;$parent_dir&quot; = &quot;$SOURCE_DIR&quot; ]; then\r\n    new_name=&quot;${base_name_no_ext}.webp&quot;\r\n  else\r\n    new_name=&quot;${parent_dir}-${base_name_no_ext}.webp&quot;\r\n  fi\r\n\r\n  # 4. Define the full output path for the new image.\r\n  output_path=&quot;${output_dir}\/${new_name}&quot;\r\n\r\n  echo &quot;Processing: \\&quot;$file\\&quot;  -&gt;  \\&quot;$output_path\\&quot;&quot;\r\n\r\n  # 5. Use &quot;convert&quot; to resize, set quality, and save to the new path and format.\r\n  #    &quot;1200x1200&gt;&quot; resizes only if the image is larger than 1200px on either side.\r\n  convert &quot;$file&quot; -resize &quot;1200x1200&gt;&quot; -quality 80 &quot;$output_path&quot;\r\n\r\n' bash {} &quot;$OUTPUT_DIR&quot; \\; # This passes the filename and output directory to the inline script\r\n\r\necho &quot;\u2705 Done.&quot;\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I had a need, well I always have a need but I finally got around to figuring this out, to resize a directory of images. I finally broke up with Adobe and had historically used the Photoshop batch functionality which was always wonky at best so that&#8217;s no longer possible. I&#8217;ve done some digging and [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[51,11],"tags":[],"class_list":["post-1402","post","type-post","status-publish","format-standard","hentry","category-cli","category-coding"],"_links":{"self":[{"href":"https:\/\/ma.rcbla.se\/blog\/wp-json\/wp\/v2\/posts\/1402","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ma.rcbla.se\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ma.rcbla.se\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ma.rcbla.se\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/ma.rcbla.se\/blog\/wp-json\/wp\/v2\/comments?post=1402"}],"version-history":[{"count":8,"href":"https:\/\/ma.rcbla.se\/blog\/wp-json\/wp\/v2\/posts\/1402\/revisions"}],"predecessor-version":[{"id":1415,"href":"https:\/\/ma.rcbla.se\/blog\/wp-json\/wp\/v2\/posts\/1402\/revisions\/1415"}],"wp:attachment":[{"href":"https:\/\/ma.rcbla.se\/blog\/wp-json\/wp\/v2\/media?parent=1402"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ma.rcbla.se\/blog\/wp-json\/wp\/v2\/categories?post=1402"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ma.rcbla.se\/blog\/wp-json\/wp\/v2\/tags?post=1402"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}