1

I have files nested in folders. In case the filename starts with a string that is repeated twice, I would like to change the filename to a name such that this string appears only once.

For example:

  • Rename "Dirty Projectors - Dirty Projectors - Search For Life.mp3" to "Dirty Projectors - Search For Life.mp3"
  • Rename "Eefje de Visser - Eefje de Visser - Bitterzoet.mp3" to "Eefje de Visser - Bitterzoet.mp3"
  • Keep "Feng Suave - Maybe Another Time.mp3" as it is.

How can I do this using command-line in Linux?

sryscad
  • 303
  • 2
  • 12
  • 1
    If you have the Perl `rename` command, you can use a regular expression that matches a string followed by the same string, by using back-references. – Barmar May 05 '20 at 14:52
  • 1
    `s/^(.*)\1/\1/` will replace a duplicate string at the beginning of a filename. – Barmar May 05 '20 at 14:52
  • Note that this means that if the filename begins with `ee` it will change to `e`. If you want the match to end with `-` you need to be more specific. – Barmar May 05 '20 at 14:53
  • @Barmar, do you mean something like `perl-rename 's/^(.*)\\1/\\1/' *.mp3`? – sryscad May 05 '20 at 20:54
  • Yes, that's what I was suggesting. – Barmar May 05 '20 at 21:50

2 Answers2

1

I combined the regex of @Barmar and the shell script of @U880D to remove any duplicate prefix in the filenames recursively. There was a problem with using find and perl-rename, so I had to do it like this:

#!/bin/bash
shopt -s globstar;
for DIR in ${PWD}/**/; do
    cd "${DIR}"
    for FILENAME in *.mp3 ; do
        NEWFILENAME=$(echo "${FILENAME}" | perl -pe 's/^(.*)\1/\1/')
        if [ "${FILENAME}" != "${NEWFILENAME}" ] ; then
            mv "${FILENAME}" "${NEWFILENAME}"
        fi
    done
done
sryscad
  • 303
  • 2
  • 12
0

How can I do this using command-line in Linux?

After some research it seems to be a bit more complex. Therefore it will probably end up in a script.

renameMusic.sh

#!/bin/bash

DIRECTORY=$1
cd ${DIRECTORY}
echo "Normalize filenames in $(pwd)"

for FILENAME in *; do
  echo
  echo "Checking file ${FILENAME}"

  # Count number of dash (-)
  NUMBER=$(grep -o '-' <<< ${FILENAME} | wc -l)
  echo "Found ${NUMBER} of dash (-)"
  
  # Check if the artist name seems to be there twice
  if [[ "${NUMBER}" -eq 2 ]]; then
    # If so, remove the double part
    NEWFILENAME=$(echo "${FILENAME}" | cut -d "-" -f 2- | sed -e 's/^[[:space:]]*//')
    echo "Going to move to new name ${NEWFILENAME}"

    # mv ${FILENAME} ${NEWFILENAME}

  fi

done

Thanks to

U880D
  • 8,601
  • 6
  • 24
  • 40
  • Please take note that I've commented out the renaming part so that it will be possible to have a dry run. I my test setup and test run it worked well. Since you have mentioned that "_I have files nested in folders._", I will leave that part to you. – U880D May 05 '20 at 16:22
  • Thank you, this works in case I put quotes around the arguments of the mv command. – sryscad May 05 '20 at 19:32
  • 1
    You should always quote your variables unless you have a good reason not to. – Barmar May 05 '20 at 21:50
  • @U880D, Actually It does not work in case the folder name contains a dash. I have tried to write `find -name "*.mp3" -type f -printf '%P\n' | xargs perl-rename 's/^(.*)\1/\1/'` but it does not change the names. It only works when I use it without the find. – sryscad May 05 '20 at 21:51
  • Thanks for the hint [When to wrap quotes around a shell variable?](https://stackoverflow.com/questions/10067266/). I'll put it into the credits. – U880D May 06 '20 at 04:52
  • @sryscad, you may take advantage from [How to loop through file names returned by find?](https://stackoverflow.com/questions/9612090/). So by enhancing the script with `# Make sure globstar is enabled shopt -s globstar for i in **/*.mp3; do # Whitespace-safe and recursive` it would work. At least it did in my test setup. – U880D May 06 '20 at 05:14