Skip to content

Instantly share code, notes, and snippets.

@scottsb
Last active April 19, 2019 10:24
Embed
What would you like to do?
Fix name of images in Magento whose names only vary by case (renaming them both in the filesystem and the database catalog). This is useful if media files need to pass through a case-insensitive filesystem, like a Mac.
#!/bin/bash
# Settings
SUFFIX=alt
MAGERUNCMD=magerun
# Sanity Checks
type $MAGERUNCMD >/dev/null 2>&1 || {
echo "ERROR: This script requires the command '$MAGERUNCMD' to be executable in the current path."
exit
}
[[ "$PWD" == *media/catalog/product ]] || {
echo "ERROR: This script should be run from the 'media/catalog/product' directory of your Magento install."
exit
}
# Directions
echo "It is highly recommended that you run the 'media:images:removeorphans' magerun extension before this."
echo '---'
if [ ! "$1" = '-f' ]; then
echo 'This script performs a dry run by default. To force changes pass flag -f.'
read -p "Press [Enter] key to continue with dry run or [Ctrl-C] to exit..."
else
echo 'WARNING: Forcing updates. Changes are destructive and cannot be undone.'
read -p "Press [Enter] key to continue with force mode or [Ctrl-C] to exit..."
fi
echo '---'
# Work Time
DUPLICATES=$(find . -path ./cache -prune -o -type f)
echo "$DUPLICATES" | sort -f | uniq -id | while read -r FILENAME; do
INDEX=1
while read OLD_FILENAME; do
NEW_FILENAME=$(echo "$OLD_FILENAME" | tr '[:upper:]' '[:lower:]' | perl -pe "s/\.([^.]*)\$/_$SUFFIX$INDEX.\1/")
if [ ! -e "$NEW_FILENAME" ]; then
eval $MAGERUNCMD db:query $([ ! "$1" = '-f' ] && printf -- --only-command) \
"'UPDATE mag_catalog_product_entity_media_gallery SET value = \"${NEW_FILENAME#.}\" WHERE BINARY value = \"${OLD_FILENAME#.}\";'" \
&& eval $([ ! "$1" = '-f' ] && printf echo) mkdir -p "${NEW_FILENAME%/*}" \
&& eval $([ ! "$1" = '-f' ] && printf echo) mv -n "$OLD_FILENAME" "$NEW_FILENAME"
else
echo "New name $NEW_FILENAME for $OLD_FILENAME already exists. Refusing to move or update DB."
false
fi
if [ $? -gt 0 ]; then
echo 'Terminating early on fatal error.'
[ "$1" = '-f' ] && echo 'Error above may need to be manually fixed.'
exit
fi
echo "Moved $OLD_FILENAME => $NEW_FILENAME."
((INDEX++))
done < <(grep -i "$FILENAME" <<< "$DUPLICATES")
done
@kojiromike
Copy link

  1. Don't put commands in variables. Instead, use a function. In particular, this will help with your -f approach (details later).
  2. In bash 4, tr '[:upper:]' '[:lower:]' can be accomplished via parameter expansion like "${foo,,}".
  3. Even in bash 3, perl -pe "s/\.([^.]*)\$/_$SUFFIX$INDEX.\1/") can be accomplished via parameter expansion like "${foo%.*}_$SUFFIX$INDEX.${foo##*.}".
  4. It's not pure bash, but if you want, you can generalize your -f pattern using Maybe.

@scottsb
Copy link
Author

scottsb commented Feb 24, 2016

Maybe is pretty awesome, definitely. Here I wanted something built-in and portable so others could use this.

I'm not sure where you're referring to putting commands in variables. Can you clarify?

@kojiromike
Copy link

MAGERUNCMD is a variable that holds a command. In almost every situation like this you get better control that is also less error prone by using a shell function.

@kojiromike
Copy link

In this case what I'm talking about is really the whole eval $MAGERUNCMD Blah blah combined with the dry run scenario. If you define slightly different functions depending on the args and dry-runniness you want, you can avoid eval altogether and have a more readable abstraction, to boot.

@scottsb
Copy link
Author

scottsb commented Feb 24, 2016

The purpose of $MAGERUNCMD is to allow you to change it easily to blah.phar or whatever you call it. I don't think functions would solve that...

@kojiromike
Copy link

What you're describing now (a script that you want people to edit, i.e. by setting MAGERUNCMD to a different value inline) is really an antipattern. If you want to support multiple names for the same command, just enumerate which ones you support. There aren't that many likely names for this command - it's going to be one of {n98-,}magerun{,.phar}.

  1. I'd recommend parameterizing that, or just picking the first executable on PATH that matches one of those names.
  2. I'd recommend not letting anyone modify the script for one-off executions, which is what you seem to be describing, IIUC.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment