Search code examples
sh

Shell script appending filenames more than once?


Sorry for the novice question. Does anyone know how to 'fix' this shell script so that it doesn't append files in sub-folders multiple times?

#!/bin/bash

# Function to append compression type to filename
append_compression_type() {
    local file="$1"
    local compression_type="$2"

    # Remove extension from filename
    local filename_no_ext="${file%.*}"

    # Append compression type to filename
    local new_filename="${filename_no_ext}_${compression_type}.${file##*.}"

    # Rename the file
    mv "$file" "$new_filename"

    echo "Renamed $file to $new_filename"
}

# Recursive function to process images in a directory
process_directory() {
    local directory="$1"

    # Find all image files in the directory
    find "$directory" -type f \( -iname "*.dds" \) | while read -r image_file; do
        # Get the compression type of the image
        local compression_type=$(identify -format '%C' "$image_file" 2>/dev/null)

        # If compression type is not empty
        if [ -n "$compression_type" ]; then
            append_compression_type "$image_file" "$compression_type"
        fi
    done

    # Process subdirectories
    find "$directory" -mindepth 1 -type d | while read -r subdirectory; do
        process_directory "$subdirectory"
    done
}

# Start processing from the current directory
process_directory "."

It works for any files in the same folder as the script but any files in sub-folder get appended multiple times as previously stated.


Solution

  • This line does not need the parentheses in the find expression:

    find "$directory" -type f \( -iname "*.dds" \) | while read -r image_file; do
    

    Did you mean to have a more complex expression inside the parens?

    The reason you're getting files processed multiple times is that the find command above outputs not only file matching the *.dds glob in the $directory but also all subdirectories. So when you then do this you are processing the *.dds files in each immediate subdirectory a second time and each *.dds file in the second level subdirectory a third time, etcetera:

    find "$directory" -mindepth 1 -type d | while read -r subdirectory; do
    

    If you really want to process each directory independent of the others add a -maxdepth 1 to your first find command. Or, just omit the second find block.