Results 1 to 10 of 14
I am looking for a method to bulk rename files using the terminal.
I don't want to use krename or any other application,I want to learn to do this in ...
- 06-18-2008 #1Just Joined!
- Join Date
- May 2006
- Posts
- 11
Bulk rename using terminal
I am looking for a method to bulk rename files using the terminal.
I don't want to use krename or any other application,I want to learn to do this in a terminal.
For example if I had these files named as follows,
abc-two_first.mp3
abc-two_second.mp3
abc-two_third.mp3
What would be the easiest way to rename the files to this?
first.mp3
second.mp3
third.mp3
I want to remove abc-two_ from all the filenames in a directory.
Would the rename command be best for this,or the mv command?
Or a combination of both commands put into a script?
- 06-19-2008 #2Linux Guru
- Join Date
- Nov 2007
- Location
- Córdoba (Spain)
- Posts
- 1,513
If you like what you see, remove "echo" and the mv commands will actually be run.Code:for file in /path/to/*; do echo mv "$file" "${file/abc-two_/}"; done
I recommend you to google for "bash string mangling" to know how to handle strings in bash. Most times if it's something simple you don't need any external programs.
About the rest of the command, google for the "advanced bash scripting guide". Regardless of it's name, it's perfectly suitable for all levels, even newcomers to bash scripting.
- 06-20-2008 #3Just Joined!
- Join Date
- May 2006
- Posts
- 11
Thanks i92guboj for the reply.
I did have a look at bash string mangling as you suggested.
I have found a way to do this with the rename command as well.
It's not so much that I don't want to use a script,but that I am looking for the very easiest way to accomplish this task.
As in my previous examples,this also works to remove what I asked about.
rename "abc-two_" " " *
I am quite stumped on one aspect though,expecially with the rename command.
When filenames begin with 01,02,03,04 etc,how can I remove these prefixes?
Every command I have looked into suggests that a "match",(oldname) is needed to be specified,then a (newname) specified to replace all the matches found.
01,02,03 etc are all different,not a match by themselves,and to enter all these numbers so a match can be found for all of them,it would be just as easy to right click,rename the file.
If the numbers 01,02,03 etc are all preceeded by a -,such as 01-,02- etc.,can this - be used to specify(maybe as a seperator) in the command to replace everything that is found before the - with a space?
Or better yet,just delete what it finds before the -?
Thanks again for the reply.
This is a bit over my head but I'm trying,and I can use all the help I can get.
- 06-20-2008 #4
Heheh, I gave this link twice yesterday. And once today
I think you will find you can manipulate strings from within bash itself quite easily.
And if you put this in a 'for' loop, like i92guboj suggested, you can rename entire directories in one command. What you'll end up with is something like this: (Untested!!!)
You could run this as one line from the command line, but that's harder to evaluate if some unexpected behavior occursCode:for FILE in /path/to/*mp3 ; do NEWNAME=${FILE##*_} # Strips everything to the left of the first '_' echo mv /path/to/$FILE /path/to/$NEWNAME # 'echo' is our safety feature done
Let us know if this is what you where looking for and if you could get it to work.Can't tell an OS by it's GUI
- 06-20-2008 #5Just Joined!
- Join Date
- May 2006
- Posts
- 11
I'm not doing this right or something,nothing happens.
I have a test directory on my desktop.
Inside are three more directories named
01- rename_a
02- rename_b
03- rename_c
I tried this from your example.
What did I do wrong?Code:for File in home/username/Desktop/test/*rename ; do > NEWNAME=${FILE##*_} > done
- 06-20-2008 #6I was thinking why you didn't include the error, but then it struck me. There was no error. The machine did what you asked.
Originally Posted by linny
But all it did was make a list of all files that /end/ in 'rename', rather than make a list of all files that /contain/ 'rename'. And then *drumroll* it sets a variable and exists. That's not very exciting is it
Try this:
Oh... And although arbitrary, names of variables are case sensitive. $File is not the same as $FILE or $file.Code:for FILE in /home/username/Desktop/test/*rename* ; do NEWNAME=${FILE##*_} echo $FILE will become $NEWNAME done
Also, it seems you have spaces in your names. That matters not a lot, but remember that normally in bash a space is a separator. You might need to escape it with '\'. Probably not now though, because in this script bash will do this for you. Just keep in mind that to call a file with the name '10 blablabla' it has to be written '10\ blablabla'.
EDIT: Don't get me wrong. I'm not trying to criticize, as I'm well aware of how easy it is to miss small mistakes that make scripts function differently than you'd expect. you wrote:
for File in home/username/Desktop/test/*rename ; do
which should have been:
for FILE in /home/username/Desktop/test/*rename* ; doCan't tell an OS by it's GUI
- 06-21-2008 #7Just Joined!
- Join Date
- May 2006
- Posts
- 11
I didn't sense that at all.I'm not trying to criticize
I read every word like it's gold.
I want my mistakes pointed out to me.
I'm wanting to learn how to get this job done,and if that's what it takes,criticize away.
You call it criticize,I call it help!
I'm not sure if I only posted the mistakes you noted here,or if I actually entered them in terminal also.
So I went back and made sure those mistakes weren't present.
Still no results at all.
I tried the command as you presented it,this is the result.
The results of echo show that something will be done,although not what I wanted.Code:$ for FILE in /home/user/Desktop/test/*rename* ; do > NEWNAME=${FILE##*_} > echo $FILE will become $NEWNAME > done /home/user/Desktop/test/01-rename_a will become a /home/user/Desktop/test/01-test_rename_a _rename_a will become a /home/user/Desktop/test/02-rename_b will become b /home/user/Desktop/test/02-test_rename_b will become b /home/user/Desktop/test/03-rename_c will become c /home/user/Desktop/test/03-test_rename_c will become c
I only want the 01,02,03 etc. removed.
I entered the command as follows anyway,without echo,because this is only a test directory.
Nothing happened at all.Code:for FILE in /home/user/Desktop/test/*rename* ; do > NEWNAME=${FILE##*_} > done
This is ls after I entered the above command.
ls
01-rename_a/ 02-rename_b/ 03-rename_c/
01-test_rename_a _rename_a 02-test_rename_b 03-test_rename_c
01- trip.txt 02- trip.txt 03- trip.txt
I am surely confused now.
Why did echo say things would happen,then they never did?
As the above echo states,two files will become a,two files will become b,etc,
You can't have two files in the same directory with the same name,so maybe this is why "nothing happened"?
Feel very free to criticize!
- 06-21-2008 #8Linux Guru
- Join Date
- Nov 2007
- Location
- Córdoba (Spain)
- Posts
- 1,513
Note that this will screw up everything if there's any strange character in the middle, this is why it's a good idea to quote filenames when you do massive operations in loops. Like this:
It's a good habit that will save you lots of pain in the future.Code:for FILE in /path/to/*mp3 ; do NEWNAME="${FILE##*_}" # Strips everything to the left of the first '_' echo mv "/path/to/$FILE" "/path/to/$NEWNAME" # 'echo' is our safety feature done
If you like what you see, then remove the echo part so the mv is actually run.
- 06-21-2008 #9Linux User
- Join Date
- Aug 2006
- Posts
- 458
- 06-21-2008 #10I shall
Originally Posted by linny 
The problem is this:
You left out the 'move' line. With 'NEWNAME=${FILE##*_}' bash just sets a new variable. But it doesn't actually do anything. (And be glad for that, as it makes setting variables that much saferCode:for FILE in /home/user/Desktop/test/*rename* ; do NEWNAME=${FILE##*_} done
)
Now to take into account this:
I take it you want 01-rename_a to be called rename_a. So we have to strip the name of 01-. And the same for the other files.
Originally Posted by linny
Then we simply tell bash to strip everything (and including) to the left of the first '-'.
Thus: "${FILE##*-}"
Also, in hindsight, there is no need for a separate NEWFILE variable. We can safely shave of an extra line from the script.
Now because this is a test directory, we'll abandon all necessary precautions and move straight to business.
cd /path/to/testdir/
sleep 3 # to feel the tension rise
There is no way to undo this. So if used against large sets of valuable data, use the cp -i rather than mv. And have the source files in another directory as the target files. And I always use echo in front of the line that does the work on the first run, to check manually if what I want to happen is what is actually gonna happen.Code:for FILE in /path/to/testdir/ ; do mv $FILE ${FILE##*-} done
Solid advice! That is indeed a good habit (and one I've been neglecting)
Originally Posted by i92guboj Can't tell an OS by it's GUI


Reply With Quote
