Home > Back-end >  Bash Cutting a Filename as a String in a Find Loop?
Bash Cutting a Filename as a String in a Find Loop?

Time:09-18

I'm trying to use the cut function to parse filenames, but am encountering difficulty while doing so in a find loop With the intention of converting my music library from ARTIST - TITLE.EXT to TITLE.EXT

So If I had the file X - Y.EXT it should yield Y.EXT as an output.

The current function is something like this:

find . -iname "*.mp3" -exec cut -d "-" -f 2 <<< "`echo {}`" \;

It should be noted that the above syntax looks a bit strange, why not just use <<< {} \; instead of the echo {}. cut seems to parse the file instead of the filename if it's not given a string.

Another attempt I had looked something like:

find . -iname "*.mp3" -exec TRACKTITLE=`echo {} | cut -d '-' -f2` \; -exec echo "$TRACKTITLE" \;

But this fails with find: ‘TRACKTITLE=./DAN TERMINUS - Underwater Cities.mp3’: No such file or directory.

This (cut -d "-" -f 2 <<< FILENAME) command works wonderfully for a single instance (although keeps the space after the "-" character frustratingly).

How can I perform this operation in a find loop?

CodePudding user response:

First thing is try to extract what you want in your file name with Parameter Expansion.

file="ARTIST - TITLE.EXT"

echo "${file#* - }"

Output

TITLE.EXT

Using find and invoking a shell with a for loop.

find . -type f -iname "*.mp3" -exec sh -c 'for music; do echo mv -v "$music" "${music#* - }"; done' sh {}  

CodePudding user response:

Below command would say what it would do, remove echo to actually run mv:

find . -iname "*.mp3" -exec sh -c 'echo mv "$1" "$(echo "$1" | cut -d - -f2)"' sh {} \;

Example output:

$ find . -iname "*.mp3" -exec sh -c 'echo mv "$1" "$(echo "$1" | cut -d - -f2)"' sh {} \;
mv ./X - Y.mp3  Y.mp3
mv ./ARTIST - TITLE.mp3  TITLE.mp3

Also notice that your cut command will leave a whitespace at the beginning of the new filename:

$ echo ARTIST\ -\ TITLE.mp3 | cut -d - -f2-
 TITLE.mp3

CodePudding user response:

You don't need the find nor the cut for this task.

for f in *' - '*.mp3; do mv -i "$f" "${f##* - }"; done

will do the job for the current directory.

If you want to descend through directories, then:

shopt -s globstar
for f in ./**/*' - '*.mp3; do
    mv -i "$f" "${f%/*}/${f##* - }"
done
  •  Tags:  
  • bash
  • Related