Following this post as a reference, I'm able to run a find and sed command without it throwing an error, but the filenames remain unchanged.

Trying to strip pronunciation_de_ from all mp3s in the current directory:


Before troubleshooting the command, here's a quick sanity check: find . -name "*.mp3"
It returns all the mp3s in the current directory. Continuing on now that we know this part works...

sed --version returns sed (GNU sed) 4.4

I run find . -name "*.mp3" -exec sed -i 's/pronunciation_de_//g' {} \;

To make sure I'm fully understanding what's happening:

find . runs the find command in the current directory.
-name "*.mp3" returns any .mp3 filetypes.
-exec executes the next command you type.
sed -i The -i switch means work on the actual files, not a (temporary) copy.

For 's/old_word/new_word/g':

  • The s sets sed to substitute mode.
  • /old_word is the word you want to replace.
  • /new_word is the word you want to replace with. In my example it'll be blank.
  • /g apply the replacement to all matches (not just the first).

{} this string will be replaced by the filename during every iteration.
\; the semicolon terminates the find command. The backslash escapes the semicolon character in case the shell tries to interpret it literally.

Most of this information I'm getting from random blogs and Stack Exchange posts:

Understanding the -exec option of find
What is meaning of {} + in find's -exec command?

I really wanted to take my time and experiment and research before posting this almost-certainly-duplicate question but I'm completely stuck!

  • 4
    sed does not rename files, it replaces text inside them; it is possible, but unlikely, that your MP3 files are now corrupted. – Michael Homer Jul 19 '19 at 5:41
  • It's ok, I backed them up before experimenting. – NomadicGoose Jul 19 '19 at 5:42
  • 1
    Read man rename for what you are actually looking for – Philippos Jul 19 '19 at 5:52
  • @Philippos dear god, I spent a few hours reading blogs and experimenting only to discover that what I was attempting was futile. Thanks for the tip. I read the man page and got it done in less than 20 seconds. Curious, in the first link I made in my post, some who commented reported it works for them. – NomadicGoose Jul 19 '19 at 6:30
  • 3
    Surely it did help them, because they are doing something completely different: They don't want to rename files, but change words inside of files. And for this purpose find with exec and sed is the perfect combination. (-: Glad I could help, anyhow. – Philippos Jul 19 '19 at 6:41

You can use find -exec ... to do the replacement in a one-line shell script.

find . -name "*.mp3" -type f -exec bash -c 'mv "$1" "${1/pronunciation_de_}"' bash {} \;

The filename {} is passed as parameter $1 to the executed bash process and ${1/pronunciation_de_} makes use of bash's parameter expansion capabilities and replaces the first occurrence of pronunciation_de_ in $1 with an empty string.

Additional option -type f makes sure to match only regular files.

| improve this answer | |
  • You don't have to launch so many bash processes with: -exec bash 'for file; do mv "$file" "${file%pronunciation_de_}"; done' bash {} + – glenn jackman Jul 19 '19 at 12:26
  • Note that if there is a subdirectory called, e.g., pronunciation_de_files, then this will remove the wrong substring from the pathnames. – Kusalananda Apr 6 at 7:10
  • @glennjackman The % in the parameter expansion in your comment removes a suffix string, not a prefix string. – Kusalananda Apr 6 at 7:11

If you want to remove the pronunciation_de_ prefix from all files with names that end in .mp3, then you should search for files with names matching pronunciation_de_*.mp3 to be sure that you don't modify other filenames by mistake (however unlikely this may be).

Don't use line-oriented text-editing tools like sed on filenames. The shell knows how to delete prefix and suffix strings from filenames efficiently.

By using find, you could solve your issue with

find . -type f -name 'pronunciation_de_*.mp3' -exec sh -c '
    for pathname do
        newname=${pathname##*/}              # removes directory path, leaves filename
        newname=${newname#pronunciation_de_} # deletes the prefix string

        mv -i "$pathname" "${pathname%/*}/$newname"
    done' sh {} +

The find command generates pathnames of files that pass the -type and -name tests and gives these in batches to a short inline sh -c script.

This script iterates over the given pathnames, and for each pathname it creates a new name by

  1. removing the initial directory path, turning a pathname like ./some/path/pronunciation_de_werden.mp3 into pronunciation_de_werden.mp3, and then
  2. removing the prefix string pronunciation_de_, turning pronunciation_de_werden.mp3 into werden.mp3.

The mv command renames the original file by moving it to the new name in the original directory (${pathname%/*} will expand to the original pathname's directory path).

| improve this answer | |

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.