将文件夹和子文件夹中的JPG图像合并为PDF。

huangapple go评论85阅读模式
英文:

ImageMagik Combining JPGS in folders and subfolders into PDFs

问题

I have a script that, when I right click on a folder, combines all pngs/jpgs/tifs inside the folder into a PDF and renames the PDF to the name of the folder it resides in.

cd %~dpnx1
for %%a in (.) do set currentfolder=%%~na
start cmd /k magick "*.{png,jpg,tif}" "%currentfolder%.pdf"

However, I have quite a lot of folders and currently have to do this one by one. How can I create a function where I can right click on a folder, which searches subfolders and combines the jpgs to PDF? So in the example below, I'm wanting to create 3 PDFs (Folder A, Folder B, and Folder C) by right-clicking and running a batch on the parent folder.

Example:

  • Parent folder (one that I would right-click and run a script from)
  • |- Folder A
  • ||- test1.jpg
  • ||- test2.jpg
  • ||- test3.jpg
  • |- Folder B
  • ||- example1.jpg
  • || - example2.jpg
  • |- Folder C
  • || Folder D
  • |||- temp.jpg
  • |||- temp2.jpg

I have also recently moved to Mac, so I'm looking to use zsh. I've had some help to attempt to use the following myself but no luck:

#!/bin/bash

# Set the output directory
output_dir='./pdfs/'

# Make the output directory if it doesn't exist
mkdir -p "$output_dir"

# Check if an input directory was provided as a command-line argument
if [ $# -eq 0 ]
then
  # Use the current directory as the input directory if none was provided
  input_dir='./'
else
  # Use the first command-line argument as the input directory
  input_dir="$1"
fi

# Find all the directories in the input directory
find "$input_dir" -type d | while read dir; do
  # Extract the base directory name
  dirname=$(basename "$dir")
  # Create a PDF file with the same name as the base directory name
  output_file="$output_dir/$dirname.pdf"
  # Find all the JPEG files in the current directory
  find "$dir" -type f -name '*.jpg' | while read file; do
    # Convert the JPEG file to PDF and append it to the output file
    convert "$file" "$file.pdf"
  done
  # Concatenate all the PDF files in the current directory into a single PDF
  gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile="$output_file" "$dir"/*.pdf
  # Remove the temporary PDF files
  rm "$dir"/*.pdf
done

Hope this helps. Thank you.

英文:

I have a script that, when I right click on a folder, combines all pngs/jpgs/tifs inside the folder into a PDF and renames the PDF to the name of the folder it resides in.

cd %~dpnx1
for %%a in (.) do set currentfolder=%%~na
start cmd /k magick "*.{png,jpg,tif}" "%currentfolder%.pdf"

However, I have quite a lot of folders and currently have to do this one by one.
How can I create a function where I can right click on a folder, which searches subfolders and combines the jpgs to PDF?
So in the example below, Im wanting to create 3 PDFS (Folder A, Folder B and Folder C) by right clicking and running batch on the parent folder.

Example:

  • Parent folder (one that I would right click and run script from)
  • |- Folder A
  • ||- test1.jpg
  • ||- test2.jpg
  • ||- test3.jpg
  • |- Folder B
  • ||- example1.jpg
  • || - example2.jpg
  • |- Folder C
  • || Folder D
  • |||- temp.jpg
  • |||- temp2.jpg

I have also recently moved to Mac so I'm looking to use zsh. I've had some help to attempt to use the following myself but no luck:

   #!/bin/bash

# Set the output directory
output_dir='./pdfs/'

# Make the output directory if it doesn't exist
mkdir -p "$output_dir"

# Check if an input directory was provided as a command-line argument
if [ $# -eq 0 ]
then
  # Use the current directory as the input directory if none was provided
  input_dir='./'
else
  # Use the first command-line argument as the input directory
  input_dir="$1"
fi

# Find all the directories in the input directory
find "$input_dir" -type d | while read dir; do
  # Extract the base directory name
  dirname=$(basename "$dir")
  # Create a PDF file with the same name as the base directory name
  output_file="$output_dir/$dirname.pdf"
  # Find all the JPEG files in the current directory
  find "$dir" -type f -name '*.jpg' | while read file; do
    # Convert the JPEG file to PDF and append it to the output file
    convert "$file" "$file.pdf"
  done
  # Concatenate all the PDF files in the current directory into a single PDF
  gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile="$output_file" "$dir"/*.pdf
  # Remove the temporary PDF files
  rm "$dir"/*.pdf
done

Hope you can help. Thank you.

答案1

得分: 2

以下是已翻译的内容:

安装 homebrew

前往这里,按照说明安装 homebrew。我不会在这里重复说明,因为它们可能会更改。

您可能需要使用以下命令安装 Xcode 命令行工具:

xcode-select --install

安装后,您需要适当设置您的 PATH。不要忽略这一步。

安装 ImageMagick

您需要执行以下命令:

brew install imagemagick

使用 Automator 创建右键菜单工作流

接下来,您需要创建一个脚本,当您右键单击目录时将执行该脚本。完成后,它将如下所示。我右键单击了桌面上的 Junk 目录,然后转到 Quick Actions 并选择了 makePDFs

将文件夹和子文件夹中的JPG图像合并为PDF。

因此,为了做到这一点,您需要启动 Automator,方法是按下<kbd>&#8984;</kbd> <kbd>SPACE</kbd> 并键入 Automator,然后在猜测时按<kbd>ENTER</kbd>。

然后选择 New DocumentQuick Action。现在按照图中的橙色区域导航,直到找到 Run Shell Script,然后将 Run Shell Script 拖到右侧并放入蓝色区域。转到 Edit 菜单,然后按<kbd>&#8984;</kbd>,然后选择 Save As,并在框中输入 makePDFs。这将是以后出现在右键菜单中的名称。

将文件夹和子文件夹中的JPG图像合并为PDF。

现在按照我所做的方式设置绿色框中的选项。

现在,替换蓝色框中的所有代码,使用下面复制的代码:

#!/bin/bash
################################################################################ 
# Recurse into all subdirectories specified in parameter and make PDF in each
# directory of all images found in there.
################################################################################ 
# Add ImageMagick from homebrew to PATH
PATH=$PATH:/opt/homebrew/bin

# Check we got a directory as parameter
if [ $# -ne 1 ] ; then
    >&2 echo "Usage: $0 DIRECTORY"
    exit 1
fi

# Find and process all subdirectories
shopt -s nullglob
while read -rd $'
#!/bin/bash
################################################################################ 
# Recurse into all subdirectories specified in parameter and make PDF in each
# directory of all images found in there.
################################################################################ 
# Add ImageMagick from homebrew to PATH
PATH=$PATH:/opt/homebrew/bin

# Check we got a directory as parameter
if [ $# -ne 1 ] ; then
    >&2 echo "Usage: $0 DIRECTORY"
    exit 1
fi

# Find and process all subdirectories
shopt -s nullglob
while read -rd $'\0' dir; do
    # Start a subshell so we don't have to cd back somewhere
    ( 
        cd "$dir" || exit 1
        # Make list of all images in directory
        declare -a images
        for image in *.jpg *.png *.tif ; do
            images+=("$image")
        done
        numImages=${#images[@]}
        if [ $numImages -gt 0 ] ; then
            pdfname=${PWD##*/}  
            magick "${images[@]}" "${pdfname}.pdf"
        fi
    )
done < <(find "$1" -type d -print0)
'
dir; do
# Start a subshell so we don't have to cd back somewhere ( cd "$dir" || exit 1 # Make list of all images in directory declare -a images for image in *.jpg *.png *.tif ; do images+=("$image") done numImages=${#images[@]} if [ $numImages -gt 0 ] ; then pdfname=${PWD##*/} magick "${images[@]}" "${pdfname}.pdf" fi ) done < <(find "$1" -type d -print0)

最后,按照我在青色框中所做的方式设置选项。

现在再次保存整个工作流,一切都应该正常工作。

英文:

There are several aspects to this question, and judging by your attempted solution, they will all be non-trivial for you. It is more than a normal question so I'll just give you an outline so you can tackle it in chunks. You'll need to:

  • install homebrew
  • install ImageMagick
  • use Automator to make a workflow for right-click
  • learn some bash scripting to recurse through directories
  • learn some ImageMagick to make PDFs

Install homebrew

Go to here and follow instructions to install homebrew. I am not repeating the instructions here as they may change.

You'll likely need to install Xcode command-line tools with:

xcode-select --install

You'll need to set your PATH properly afterwards. Don't omit this step.


Install ImageMagick

You'll need to do:

brew install imagemagick

Setup workflow with Automator for right-click

Next you need to make a script that will be executed when you right-click on a directory. It will look like this when we have done it. I right-clicked on the Junk directory on my desktop and went down to Quick Actions and across to makePDFs.

将文件夹和子文件夹中的JPG图像合并为PDF。

So, in order to do that you need to start the Automator by clicking <kbd>&#8984;</kbd> <kbd>SPACE</kbd> and typing Automator and hitting <kbd>ENTER</kbd> when it guesses.

Then select New Document and Quick Action. Now navigate the orange areas in the diagram till you find Run Shell Script then drag Run Shell Script over to the right side and drop it in the blue zone. Go on the Edit menu and click <kbd>&#8984;</kbd> and then Save As and enter makePDFs in the box. This is the name that will appear in future on your right-click menu.

将文件夹和子文件夹中的JPG图像合并为PDF。

Now set the options in the green box like I have done.

Now replace all the code in the blue box with the code copied from below:

#!/bin/bash
################################################################################
#&#160;Recurse into all subdirectories specified in parameter and make PDF in each
# directory of all images found in there.
################################################################################
#&#160;Add ImageMagick from homebrew to PATH
PATH=$PATH:/opt/homebrew/bin

# Check we got a directory as parameter
if [ $# -ne 1 ] ; then
   &gt;&amp;2 echo &quot;Usage: $0 DIRECTORY&quot;
   exit 1
fi

# Find and process all subdirectories
shopt -s nullglob
while read -rd $&#39;
#!/bin/bash
################################################################################
#&#160;Recurse into all subdirectories specified in parameter and make PDF in each
# directory of all images found in there.
################################################################################
#&#160;Add ImageMagick from homebrew to PATH
PATH=$PATH:/opt/homebrew/bin
# Check we got a directory as parameter
if [ $# -ne 1 ] ; then
&gt;&amp;2 echo &quot;Usage: $0 DIRECTORY&quot;
exit 1
fi
# Find and process all subdirectories
shopt -s nullglob
while read -rd $&#39;\0&#39; dir; do
# Start a subshell so we don&#39;t have to cd back somewhere
( 
cd &quot;$dir&quot; || exit 1
#&#160;Make list of all images in directory
declare -a images
for image in *.jpg *.png *.tif ; do
images+=(&quot;$image&quot;)
done
numImages=${#images[@]}
if [ $numImages -gt 0 ] ; then
pdfname=${PWD##*/}  
magick &quot;${images[@]}&quot; &quot;${pdfname}.pdf&quot;
fi
)
done &lt; &lt;(find &quot;$1&quot; -type d -print0)
&#39; dir; do # Start a subshell so we don&#39;t have to cd back somewhere ( cd &quot;$dir&quot; || exit 1 #&#160;Make list of all images in directory declare -a images for image in *.jpg *.png *.tif ; do images+=(&quot;$image&quot;) done numImages=${#images[@]} if [ $numImages -gt 0 ] ; then pdfname=${PWD##*/} magick &quot;${images[@]}&quot; &quot;${pdfname}.pdf&quot; fi ) done &lt; &lt;(find &quot;$1&quot; -type d -print0)

Finally, set the options like I did in the cyan coloured box.

将文件夹和子文件夹中的JPG图像合并为PDF。

Now save the whole workflow again and everything should work nicely.

答案2

得分: 1

对于bash,请尝试以下代码(已在Linux上测试):

for d in */; do convert "$d"/*.{png,jpg,tif} "$d/${d%/}.pdf" ; done

以慢动作解释:

  • for d in */:在当前目录中循环遍历所有目录(/限制了匹配到目录)。变量$d包含目录名称,且名称以/结尾。
  • "$d"/*.{png,jpg,tif}:目录"$d"中所有具有pngjpgtif扩展名的文件。
  • "$d/${d%/}.pdf":目录名称、斜杠、去除结尾斜杠的目录名称,以及.pdf

如果你仔细观察,代码中的显式/并不是必需的,因为$d的末尾已经有一个,但保留它们可以使代码更具可读性,多个//会合并为单个/

但是,这段代码可能会抱怨找不到png/jpg/tif文件。稍微不同的形式可以使其更友好:

shopt -s extglob # 这可能已经默认设置
for d in */; do convert "$d"/*.@(png|jpg|tif) "$d/${d%/}".pdf ; done

对于zsh,可能是这样的(未经测试):

# shopt -s extglob # 不需要shopt
for d in */; do convert "$d"/*.png(N)  "$d"/*.jpg(N) "$d"/*.tif(N) "$d/${d%/}".pdf ; done

需要注意的是,如果没有匹配的模式,命令将只是convert whatever_output.pdf,然后你将获得内置帮助信息。

区别在于,*.{png,jpg,tif}在进行任何模式匹配之前被展开为*.png *.jpg *.tif,因此代表了三个文件模式,shell会尝试逐个匹配每个模式(并在没有匹配的情况下保留文字模式),而*.@(png|jpg|tif)是一个单一的文件模式,可以匹配任何三个扩展名中的任何一个。这也可能会对你产生影响,因为文件不会按相同的顺序出现,*.{png,jpg,tif}列出所有的PNG,然后是JPG,然后是TIF,而*.@(png|jpg|tif)将它们按字母顺序排序,不考虑扩展名。

英文:

For bash, try this (tested on Linux):

for d in */; do convert &quot;$d&quot;/*.{png,jpg,tif} &quot;$d/${d%/}.pdf&quot; ; done

In slo-mo:

  • for d in */: loop on all directories in current directory (the / restrict matches to directories)). Variable $d contains the directory name, and name has a final /.
  • &quot;$d&quot;/*.{png,jpg,tif}: all files with png, jpg or tif extension in the directory "$d"
  • &quot;$d/${d%/}.pdf&quot;: the directory name, a slash, the directory name with the ending slash removed, and .pdf`

If you look carefully, the explicit /s in the code aren't necessary since there is already one at the end of $d, but leaving them in makes the code a bit more readable and the multiple '//' are coalesced into a single one.

This code may however complain that there are no png/jpg/tif. A slightly different form makes it behave more nicely:

shopt -s extglob # this is possibly already set by default
for d in */; do convert &quot;$d&quot;/*.@(png|jpg|tif) &quot;$d/${d%/}&quot;.pdf ; done

for zsh this could be (untested!):

# shopt -s extglob # no shopt necessary
for d in */; do convert &quot;$d&quot;/*.png(N)  &quot;$d&quot;/*.jpg(N) &quot;$d&quot;/*.tif(N) &quot;$d/${d%/}&quot;.pdf ; done

with the caveat that if no pattern matches, the command will just be convert whatever_output.pdf and you will get the built-in help.

The difference is that *.{png,jpg,tif} is expanded to *.png *.jpg *.tif before any pattern matching is done, so this represents three file patterns and the shell tries to match each pattern in turn (and leaves the literal pattern in case there is no match), while *.@(png|jpg|tif) is a single file pattern that matches any of the three extensions. This can also make a difference for you because the files do not appear in the same order, *.{png,jpg,tif} lists all the PNG, then the JPG,then the TIF, while *.@(png|jpg|tif) has them all sorted in alphabetical order without regard for the extension.

huangapple
  • 本文由 发表于 2023年1月6日 15:05:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75027936.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定