0

So my specific problem is I downloaded a few albums of mp3s, that don't have track numbers in their title, so they default to alphabetic sort, which is clearly not ideal. I want to be able to quickly rename them with a terminal command where I use wildcards to sort through the fluff. So I've tried this from a few angles without success, and want some guidance.

On the one hand, I want to try something like mv *someSongN* 01-{reference original name here}. I am not clear, in the second argument to mv, how I reference the original file name, but prepended with a 01-.

The other tack I tried was to create a temporary bash variable, followed by a mv command. I tested this out by creating a test file without any extension -- touch test. I found echo and mv treat the wildcard differently. So, pretend the test file is the only in the directory beginning te-- ... var=te*; echo $var returns test but var=te*; mv $var $var.txt returns te*.txt. So what strategy do I use here. I could also do this with a graphical file manager but I've done that before and found it very tiresome.

cfye14
  • 117
  • 6
  • Have you tried using the `find` command? You can run `find` with wildcards and this returns the filename which you could then set as a variable. – IT_User Apr 04 '16 at 20:10
  • Do the tracks have [ID3 tags](https://en.wikipedia.org/wiki/ID3) within them? – dawg Apr 04 '16 at 20:12
  • @dawg, it looks like they do, but for whatever reason the music players I've tried just play the files thru the alphabetic sort, even while displaying the track number. At any rate, I like a little filename metadata. – cfye14 Apr 04 '16 at 20:19
  • 1
    You can use `Perl` or `Python` to read the ID3 tags and restore the file name (and directory for Artist/Album type organization) using the ID3 tag -- assuming it is accurate. – dawg Apr 04 '16 at 20:20
  • A quick work-around for your `var=te*; mv $var $var.txt`, could be... `var=te*; var=$(echo ${var}) ; mv $var $var.txt` This will reset your **var** variable to what echo displays. – IT_User Apr 04 '16 at 20:47

3 Answers3

0

Here is an example using the find command

#!/bin/bash
if [[ $1 = "" ]] ; then
  echo "Please run the command specifying the filename you are searching for..."
  exit
fi
for i in $(find . -type f -name "$1" | tr -d './') ; do
  echo ${i}
  mv ${i} 01-${i}
done

You would then run...

./scriptName "*someSongN*"
IT_User
  • 729
  • 9
  • 27
  • You could turn `01` into another variable that is in a loop so you would have 01-filename 02-Filename 03-Filename etc. etc. – IT_User Apr 04 '16 at 20:20
  • so typically `find` outputs the current directory like `./thisisafile`, so is there a way built in to find to exclude that. I could add `cut -c 3-` to a pipe but eh – cfye14 Apr 04 '16 at 22:12
  • if i get the chance, I will upvote. Helpful throughout post, just found @karafka's answer slightly more efficient. – cfye14 Apr 04 '16 at 23:04
  • @cfye14 I modified the code to include `tr -d './'` in the for loop. this will remove the "./" – IT_User Apr 05 '16 at 15:32
  • @cfye14 Not sure of a built in way yet, but I will ponder this and see if I can remove the pipe. – IT_User Apr 05 '16 at 15:35
  • ah yes, `tr` is more suitable – cfye14 Apr 06 '16 at 00:49
  • this isn't how `tr` works. `tr -d './` will delete either of the `.` or `/` in the "set". – cfye14 Apr 09 '16 at 02:25
  • what would work but is a little more cumbersome is `sed 's/\.\///g'` – cfye14 Apr 09 '16 at 02:31
  • Hmmm. Worked perfectly on my end. I'll test this again Monday and get back to you – IT_User Apr 09 '16 at 02:58
0

Do it as a batch process. Create a map file with columns fromName toName, run through a script for renaming.

while read a b; do mv "$a" "$b"; done < filemap

to create filemap, ls and paste

ls -1 > files; paste files files > filemap; rm files

and manually edit the filemap file to add required prefixes.

karakfa
  • 66,216
  • 7
  • 41
  • 56
0

when you just want to move one file, you can create (an inline) function like

$ mvd() { mv $1 $2$1; }

and use it like

$ mvd test.mp3 01-

which will move the file test.mp3 to 01-test.mp3.


By using find, you can do this operation on multiple files, but that will result in all files starting with only one prefix (find . -type f -name ${pattern} -exec mvd {} ${prefix}).

Another option is using find . -type f -name ${pattern} and iterate over it using for. Then, you can implement a counter:

$ i=0; for file in $(find . -type f -name ${pattern}); do mv $file $i-$file; let i+=1; done

Greetings Fabian

Fabian Damken
  • 1,477
  • 1
  • 15
  • 24
  • thx. I can't quite get this to work, but I can use the function for single cases. Also it seems more work is needed [here](https://stackoverflow.com/questions/4321456/find-exec-a-shell-function) to use a custom bash function with find -exec. – cfye14 Apr 04 '16 at 21:58
  • with the for loop, how would I deal with the pattern changing? – cfye14 Apr 04 '16 at 21:58