0

I would like help with a shell script for macOS to rename files with a certain pattern. The script would handle only one file, not multiple.

Here are three examples:

a. Public Talks_ (189) Walking With God Brings Blessings Now and Forever — Chris Ruscher 10_28_2023.mp3

would become

189 - Walking With God Brings Blessings Now and Forever - Chris Ruscher - 2023-10-28-0900.mp3

b. Public Talks_ (55) How Can You Make a Good Name With God? — Gregory Duhon 11_4_2023.mp3

would become

055 - How Can You Make a Good Name With God? - Gregory Duhon - 2023-11-04-0900.mp3

c. Public Talks_ (9) Walking With God Brings Blessings Now and Forever — Chris Ruscher 10_28_2023.mp3

would become

009 - Walking With God Brings Blessings Now and Forever - Chris Ruscher - 2023-10-28-0900.mp3

So in essence, the final format and order should be: track number, title, speaker name, and timestamp.

  1. drop the prefix “Public Talks_ “
  2. Isolate the track number as a 3 digit number with leading zeros as needed
  3. Dashes in between all 4 elements
  4. Reformat date to a timestamp like yyyy-mm-dd-0900

I would then take the shell script and use it per file in this dialog box (no need to iterate):

Please note the variable for the file being passed on to the shell script needs to be written as "$1" as seen in the dialog box below.

insert shell script window

Someone helped me create one but it only works for Windows and doesn't take into account "$1" as the file and is set to do multiple files. I need it to work on macOS for one file at a time.

#!/bin/bash for file in *.mp3; do # Remove "Public Talks_" newname=${file#"Public Talks_ "} # Extract the track number and pad with leading zeros track=$(echo $newname | grep -o -E '\([0-9]+\)' | tr -d '()' | awk '{printf "%03d\n", $0}') # Remove track number and trailing spaces newname=$(echo $newname | sed -E 's/\([0-9]+\)//' | sed 's/^ *//') # Extract the title and speaker title=$(echo $newname | awk -F '—' '{print $1}' | sed 's/ *$//') speaker=$(echo $newname | awk -F '—' '{print $2}' | awk '{print $1, $2}') # Extract the date and reformat date=$(echo $newname | grep -o -E '[0-9]+_[0-9]+_[0-9]+' | tr '_' '-' | awk -F- '{print $3"-"$1"-"$2"-0900"}') # Concatenate all elements with dashes newname="$track - $title - $speaker - $date.mp3" # Rename the file mv "$file" "$newname" done 

Can anyone translate it into the proper macOS syntax or write a shell script that is even more concise?

5
  • Note that your input file names seem to contain (U+2014 em dash) characters while your expected output expects - (U+002D regular hyphen-minus). That awk -F '—' doesn't make sense other than it seems to be the double-encoding of em dash via the windows-1252 charset (as in echo — | iconv -t utf-8 | iconv -f windows-1252 -t utf-8).CommentedNov 18, 2023 at 14:34
  • @StéphaneChazelas I agree. I went back to your zmv code and it is perfect! I adjusted it to give 2 digit month and year. And it works flawlessly, when I use it in Terminal. However, I want to use it as a Folder Action in the Mac Finder. When I do, it errors out to "[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil objects[0]". Would you have any ideas?CommentedNov 19, 2023 at 2:18
  • @StéphaneChazelas - Here is the tweaked code: zmv '*_ \((<0-999>)\)(* )—( * )(<1-12>)_(<1-31>)_(<1900-2100>)(.mp3)' '${(l[3][0])1} -$2-$3- $6-${(l[2][0])5}-${(l[2][0])4}-0900$7'CommentedNov 19, 2023 at 2:22
  • Ah. Thanks, I had missed that requirement, I've added it to my answer. No idea about your Mac Finder issue, I don't have access to macos machines.CommentedNov 19, 2023 at 9:44
  • Understood. Many, many thanks for the help. It was invaluable. Hopefully someone else can help with the Mac issue.CommentedNov 19, 2023 at 12:35

1 Answer 1

1

In zsh, from within the directory that contains those files, you'd run:

autoload -Uz zmv zmv -n '*_ \((<0-999>)\)(* )—( * )(<1-12>)_(<1-31>)_(<1900-2100>)(.mp3)' \ '${(l[3][0])1} -$2-$3- $6-${(l[2][0])5}-${(l[2][0])4}-0900$7' 

Example:

$ autoload -Uz zmv $ zmv -n '*_ \((<0-999>)\)(* )—( * )(<1-12>)_(<1-31>)_(<1900-2100>)(.mp3)' \ '${(l[3][0])1} -$2-$3- $6-${(l[2][0])5}-${(l[2][0])4}-0900$7' mv -- 'Public Talks_ (189) Walking With God Brings Blessings Now and Forever — Chris Ruscher 10_28_2023.mp3' '189 - Walking With God Brings Blessings Now and Forever - Chris Ruscher - 2023-28-10-0900.mp3' mv -- 'Public Talks_ (55) How Can You Make a Good Name With God? — Gregory Duhon 11_4_2023.mp3' '055 - How Can You Make a Good Name With God? - Gregory Duhon - 2023-4-11-0900.mp3' mv -- 'Public Talks_ (9) Walking With God Brings Blessings Now and Forever — Chris Ruscher 10_28_2023.mp3' '009 - Walking With God Brings Blessings Now and Forever - Chris Ruscher - 2023-28-10-0900.mp3' 

Remove the -n (dry-run) if happy.

If that has to be a shell script that takes the file names as arguments:

#! /bin/zsh - set -o extendedglob pattern='(#b)*_ \((<0-999>)\)(* )—( * )(<1-12>)_(<1-31>)_(<1900-2100>)(.mp3)' ret=0 for file { if [[ $file = $~pattern ]] { argv=( "$match[@]" ) mv -i -- $file "${(l[3][0])1} -$2-$3- $6-${(l[2][0])5}-${(l[2][0])4}-0900$7" || ret=$? } else { print -ru2 "Skipping $file which doesn't match the pattern" } } exit $ret 

But you'd be missing on the extra safeguards of zmv.

Note that we're looping over all the arguments of the script instead of just processing the first ($1).

9
  • Thank you for the response. It errored out. Your code doesn't seem to have the $1 variable.CommentedNov 18, 2023 at 12:23
  • @AllexValentin, that's what that zmv command does. Here I show its dry-run output which shows the mv command it would run on those three files.CommentedNov 18, 2023 at 12:25
  • Understood. Thank you! Can you adjust for the $1 variable. I think that is where the error comes from.CommentedNov 18, 2023 at 12:28
  • 1
    @AllexValentin what exactly is "the app I am using to handle the files"?CommentedNov 18, 2023 at 14:05
  • 1
    @steeldriver, it smells like this.CommentedNov 18, 2023 at 14:43

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.