1

Summary

I have thousands of pictures that were titled in full sentences. I am trying to automate a way to do clean them up with a single script, and then reuse that script as I add more pictures.

The general idea is to find the pictures that are malformed, then process them through a set of renames and formatting.

So far, I've used tools like 'find' and 'SED' and 'Rename' and even tried 'mv' and such....

Needs

  1. Remove words like in, an, the, on, etc. and commas, underscores, etc.

  2. Rename the first word in the file to the parent directory name as
    (Parent Directory) [filename nouns verbs tags].jpg.

  3. Title Case Every Word That Is Left.

  4. Run this against a folder and it's sub-folders.

  5. Remove duplicate words

  6. Create the format of "(Parent Folder) [Tag Tag Tag Tag Tag].ext"
    example: "/path/to/my/files/travel/Denver/(Denver) [July 2019 Sarah Saw Blue Bear].jpg"

Example Process:

  1. Find any files that do not start with "("
    (eliminating some search folders and special files that shouldn't be touched)

find /path/to/my/files/travel -not -path '*/\.*' -not -path "*Unsorted*" -not -path "*Tools*" -not -path "*Searches*" -type f \( -not -iname '(*' -not -iname '_*' -not -iname 'Icon*' -not -iname '∆*' \)

Results of the find

  • "/path/to/my/files/travel/Denver/My trip to Denver on July 2019 with Sarah and saw the blue bear.jpg"
  • "/path/to/my/files/travel/Tampa/Tampa Trip for work, 2018.png"
    . . . . and about 36000 other photos that I haven't iterated through.
  1. Pass those found files to a renamer, like SED or Rename? http://plasmasturm.org/code/rename
    rename -v --camelcase -X --trim --subst-all word1 word2 {filename}
    I suspect rename is just a wrapper for SED, but.. whatever works

  2. Iterate through all the potential renames that will need to be made, without replacing fractions of the word.
    for example, replacing "the" with "" should not trim "These" into "se"

Original Replacement
"The" ""
"In" ""
"Jul " "July"
"Colo Springs" "Colorado Springs"
"Daughter" "Sarah Jones"
" " " " <-- Double space to single space
"," " " <-- Replace commas with spaces, etc.

  1. Correct duplications.
    In the Example for Tampa, simply adding (Tampa) to the name would result in "(Tampa) Tampa Trip Work 2018.png"

Result

When complete, the whole process would have renamed our example files:

  • "/path/to/my/files/travel/Denver/My trip to Denver on July 2019 with Sarah and saw the blue bear.jpg"
    becomes

  • "/path/to/my/files/travel/Denver/(Denver) July 2019 Sarah Saw Blue Bear.jpg"
    and

  • "/path/to/my/files/travel/Tampa/Tampa Trip for work, 2018.png"
    becomes

  • "/path/to/my/files/travel/Tampa/(Tampa) Trip Work 2018.png"

Missing Piece(s):

  • I don't know how to pass a set of replacement words per file and iterate each file found in the find process
  • I don't know how to capture the parent directory name for the file
  • I am not sure how to eliminate duplicates

Am I even going down the right path here?
Any help would be appreciated.

Update

I was able to find this https://stackoverflow.com/a/49778528/688243
So I applied it to my 'find' - so part of the puzzle is done - I have figured out how to find the files I need to correct.
I think the next step would be to iterate 'rename' or 'SED' through each file, by replacing the 'echo'....

IFS=$'\n'
for i in $(find /path/to/my/files/travel -not -path '*/\.*' -not -path "*Unsorted*" -not -path "*Tools*" -not -path "*Searches*" -type f \( -not -iname '(*' -not -iname '_*' -not -iname 'Icon*' -not -iname '∆*' \) ); 
do
    echo "$i"
done
unset IFS
10
  • 2
    A better design, IMHO is: Write a script in the language you feel comfortable with, that does whatever to a list of files (processes each file, detecting duplicates & undesired words, eventually doing the renaming (use echo mv until you're happy)), feed it with find . -type f -print0 | xargs -0 -r yourscript. Read man bash find xargs.
    – waltinator
    Jul 27, 2021 at 1:16
  • 3
    One problem you will face is computer interpretation of natural human languages. I would suggest you do no immediately rename the files, but create something such as a CSV file where the first entry (column) is the original name, and then each additional entry is a part extracted from the original name, such as "First Word". You can then stage each step until you are satisfied with the results of that step before moving to the next step. Once you have completed everything, then use that CSV file to do the actual renaming.
    – C. M.
    Jul 27, 2021 at 4:48
  • @waltinator I agree, the plan was to make this into a bash .sh file to run nightly, so that anytime new pics are added to the folders, they would be correctly renamed. Jul 28, 2021 at 21:27
  • @C.M. I have a set of test files that I plan on using that will include variants of the words i plan to remove or rename; I feel that if I can eliminate cut off (stripping 'the' from 'these' while still removing valid 'the'), I will be successful in full word corrections. Jul 28, 2021 at 21:29
  • As given, are you in full control of the input file names? Can.you.have.files.named.like.this.txt? Or_like_this? The idea of encoding file meta data in file names has been around for a very long time. There are many tools which do so, with varying successes--and failures. Another question is, how significant are the file names? I.E., can you output a HTML file with links to the files, which can be cross-linked by tags, date, etc, and not really care what the actual filename is?
    – C. M.
    Jul 29, 2021 at 1:58

1 Answer 1

0

I'm not sure if this is the best answer, but I have resolved my issue.

A file in my 'travel' folder named

"this was my sister Jamie's trip to vegas last summer_2019.jpg"

gets successfully renamed to
"(Travel) [Sister Jamie Trip Vegas Last Summer 2019].jpg"

Here's the solution I came up with:

#!/bin/sh
# # Finds items in the specified folder. 
# # Recursively renames them to correct. 

# Corrects for whitespace
IFS=$'\n'
# Creates Loop using the results of FIND
for i in $( find /mydrive/pathname -not -path '*/\.*' -not -path "*Unsorted*" -not -path "*Tools*" -not -path "*Searches*" -type f \( -not -iname '(*' -not -iname '_*' -not -iname 'Icon*' \)); 
do
# Gets the Basename of the file
b="$(basename -- $i)"
# Gets the Parent Folder name
p="$(basename "$(dirname "$i")")"
# Gets the Directory of the file
d="$(dirname "$i")"


## Testing the Variables 
# echo "$b" 
# echo "$p"
# echo "$d"
# echo "$i"
##

# Change Directory to the file location
cd "$d"/

# Perform Rename actions and iterate the file. 
 # -X = save the file extension
 # -S = replace all occurrences of the word 
 # -A = Prepend to the filename
 # -a = append to the end
 # --camelcase = Capitalize Each Word
 
 # The format is -S " OriginalWord "    "ReplaceWord" \  

 rename -X  --camelcase \
 -S " The "     " " \
 -S " If "      " " \
 -S " In "      " " \
 -S " For "     " " \
 -S " And "     " " \
 -S " Of "      " " \
 -S " A "       " " \
 -S " Is "      " " \
 -A "($p) [" \
 -a "]" \
 -S " ]"        "]"  \
 -S "]]]"       "]"  \
 -S "]]"        "]"  \
 -S "[[["       "["  \
 -S "[["        "["  \
 -S " ("        "("  \
 -S "((("       "("  \
 -S "(("        "("  \
 -S ")))"       ")"  \
 -S "))"        ")"  \
 -S "(]"        ""   \
 -S "__"        " "  \
 -S "_"         " "  \
 -S "   "       " "  \
 -S "  "        " "  \
 -S "..."       "."  \
 -S ".."        "."  \
 -S "'s"        "s"  \
 "$b"
 
done
# Removes IFS setting
unset IFS

There are more -S iterations for replace, but I only put a few examples in-line.

Thanks for everyone's help, and a lot of research on bash, rename, perl's renaming conventions, etc. lol.

1
  • Oh, and I wanted them one-per-line so that I can continue to add or remove as my needs change. Jul 30, 2021 at 0:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.