How do I this shell (.zsh) script to put files into nested folders?

39 views Asked by At

This script takes files from nested folders and mass converts them to PDF. This part works fine. The problem is that the PDFs generated are put into the parent folder only - and I want each one to end up in the folder it was originally found in.

#!/bin/zsh

source_dir="/source/folder/of/documents"

input_file_types=(doc docx xls xlsx)
output_file_type="PDF"

echo "# Using source directory " "$source_dir"
echo "# Converting "$input_file_types" to "$output_file_type

# loop over the types and convert
for input_file_types in "${input_file_types[@]}"
do
        # Find the files and pipe the results into the read command.  The read command properly handles spaces in directories and files names.
        # find "$source_dir" -name *.$input_file_type | while read in_file
        find "$source_dir" -name "*.$input_file_types" -print0 | while IFS= read -r -d $'\0' in_file
        # In order to correctly handle filenames containing whitespace and newline characters, you should use null delimited output. That's what the -print0 and read -d $'\0' is for.
        do
                echo "Processing…"
                echo "> Input "$in_file

                # Convert the file
                sudo /Applications/LibreOffice.app/Contents/MacOS/soffice --convert-to pdf:writer_pdf_Export --outdir "$source_dir" $in_file

                echo "> Finished "$out_file "\n\n"
        done
done

echo "DONE CONVERTING FILES"

I know that the problem lies in the --outdir "$source_dir" command, but I'm unsure of what to replace that with so the file shows up in the nested folder the file was found in.

Note that I have attempted to remove the --outdir "$source_dir" command entirely - but that just dumps the resulting PDF files into the folder the script was run from.

2

There are 2 answers

1
user2985384 On

Nevermind, I figured it out:

#!/bin/zsh

source_dir="/source/folder/of/documents"

input_file_types=(doc docx xls xlsx)
output_file_type="PDF"

echo "# Using source directory " "$source_dir"
echo "# Converting "$input_file_types" to "$output_file_type

# loop over the types and convert
for input_file_types in "${input_file_types[@]}"
do
        # Find the files and pipe the results into the read command.  The read command properly handles spaces in directories and files names.
        # find "$source_dir" -name *.$input_file_type | while read in_file
        find "$source_dir" -name "*.$input_file_types" -print0 | while IFS= read -r -d $'\0' in_file
        # In order to correctly handle filenames containing whitespace and newline characters, you should use null delimited output. That's what the -print0 and read -d $'\0' is for.
        do
                echo "Processing…"
                echo "> Input: "$in_file

                file_path="${in_file%/*}/"
                echo "> File path: "$file_path

                # Convert the file
                echo "*** Converting "$in_file
                sudo /Applications/LibreOffice.app/Contents/MacOS/soffice --convert-to pdf:writer_pdf_Export --outdir "$file_path" $in_file

                echo "> Finished: "$out_file "\n\n"
        done
done

echo "DONE CONVERTING FILES"
0
Gairfowl On

In zsh, the :h modifier will get the directory from a filename, so that can be used to set the output location:

--outdir "${in_file:h}"

There are some other shell operators available that can shorten the loop a bit, while still supporting filenames with spaces and newlines:

#!/usr/bin/env zsh
source_dir="/source/folder/of/documents"
input_file_types=(doc docx xls xlsx)

file_pattern="${source_dir}/*.(${(j:|:)input_file_types})"
for in_file in ${~file_pattern}; do
    /Applications/LibreOffice.app/Contents/MacOS/soffice \
        --convert-to pdf:writer_pdf_Export \
        --outdir "${in_file:h}" \
        "${in_file}"
done

Note that this does not use sudo; that shouldn't be necessary when dealing with files like this. If the command will not work without sudo, that may indicate a directory permissions issue.