LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 11-08-2007, 05:29 PM   #1
tmbigrigg
LQ Newbie
 
Registered: Nov 2007
Location: Canton, Ohio
Distribution: Ubuntu, Mepis, Damn Small Linux,
Posts: 10

Rep: Reputation: 0
changing filename using Bash Script


I am relatively new at scritping and would like to know if anyone can point me in the right direction here. What I am trying to do is write a script that will replace a single character "b" in a multiple file names with "_". I have a directory for pictures with several sub-directories each containing several pictures. I want to keep the naming scheme consistant for all files. Most of the files are 100_xxxx.jpg however a small number of files have the underscore replaced with a lowercase b. I want to be able to search all the files and anywhere 100bxxxx.jpg appears I want to replace the b with an underscore. I am not sure how to write this and have the script search multiple directories. I am thinking that sed would a good option to start with but I am just not sure.

Below is a sample of the directory structure that I am working with.

/dev/hdb5/2005-06-11/100_1643.jpg
/dev/hdb5/2006-10-21/100b5006.jpg
/dev/hdb5/2004-12-24/100_0156.jpg
/dev/hdb5/2006-10-21/100_4940.jpg
/dev/hdb5/2006-06-25/100b0042.jpg
/dev/hdb5/2006-10-21/100b5054.jpg
/dev/hdb5/2006-10-21/100b4880.jpg


Thank you for any assistance.

Tmbigrigg
 
Old 11-08-2007, 06:22 PM   #2
matthewg42
Senior Member
 
Registered: Oct 2003
Location: UK
Distribution: Kubuntu 12.10 (using awesome wm though)
Posts: 3,530

Rep: Reputation: 63
I find your path a little unlikely. /dev/hda5 is a special file, and not a directory with sub-directories. Perhaps you mean /media/hda5 or some other path?

In any case, if you have Perl installed you will probably have access to the rename program (sometimes called prename). This program, and is very convenient, especially if you are already familiar with perl regular expressions and related operators.

I will in this example use the path you specified, but I think it is a mistake:
Code:
find /dev/hdb5/200* -type f |xargs rename -n 'tr/b/_/g'
This will print a list of the renaming which will be done... the -n option to rename means "no action" - it just prints what would be done if the -n option is omitted. First run the command above check it will do what you want and then run it like this:
Code:
find /dev/hdb5/200* -type f |xargs rename 'tr/b/_/g'
 
Old 11-08-2007, 06:25 PM   #3
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
You can use the find command to recursively search into subdirectories
Code:
find . -name "100b????.jpg"
and when you are pretty sure of the result, you can rename the files by
Code:
find . -name "100b????.jpg" | xargs rename 100b 100_
I used '100b' and '100_' (not just 'b' and '_') in the rename command to prevent it tries to change the directory name, since rename change the first occurrence of the 'from' pattern. See man rename for details.

Edit: sorry matthewg42, I did not see your reply before posting!

Last edited by colucix; 11-08-2007 at 06:28 PM.
 
Old 11-08-2007, 10:58 PM   #4
tmbigrigg
LQ Newbie
 
Registered: Nov 2007
Location: Canton, Ohio
Distribution: Ubuntu, Mepis, Damn Small Linux,
Posts: 10

Original Poster
Rep: Reputation: 0
Thanks

You are correct I made a mistake on the path it was media/hda5... I was writing the question while at work and could not remember the exact path.

Thank you I will try your suggestion very soon.

Again thank you very much.

tmbigrigg
 
Old 11-08-2007, 11:07 PM   #5
jschiwal
Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 655Reputation: 655Reputation: 655Reputation: 655Reputation: 655Reputation: 655
You can also use variable substitution:
for file in *.jpg; do
mv "$file" "${file//b/_}"
done

Last edited by jschiwal; 11-09-2007 at 01:11 AM.
 
Old 11-09-2007, 10:13 PM   #6
tmbigrigg
LQ Newbie
 
Registered: Nov 2007
Location: Canton, Ohio
Distribution: Ubuntu, Mepis, Damn Small Linux,
Posts: 10

Original Poster
Rep: Reputation: 0
When I run the command
Code:
find /media/hdb6/200* -type f |xargs rename -n 'tr/b/_/g'
I am getting the following returned to me:

Code:
Bareword found where operator expected at (eval 1) line 1, near "tr/b/_/g"
syntax error at (eval 1) line 2, near "tr/b/_/g
"
xargs: rename: exited with status 255; aborting
 
Old 11-10-2007, 04:49 AM   #7
Disillusionist
Senior Member
 
Registered: Aug 2004
Location: England
Distribution: Ubuntu
Posts: 1,013

Rep: Reputation: 83
try:

Code:
find /media/hdb6/200* -type f |xargs rename 's/100b/100_/'
As previously stated by colucix, it is not accurate to replace all instances of 'b' in a file name.

If you have directories with '100b' in the path then this would still fail, otherwise should do what you are after.
 
Old 11-10-2007, 05:19 AM   #8
unSpawn
Moderator
 
Registered: May 2001
Posts: 27,675
Blog Entries: 54

Rep: Reputation: 2954Reputation: 2954Reputation: 2954Reputation: 2954Reputation: 2954Reputation: 2954Reputation: 2954Reputation: 2954Reputation: 2954Reputation: 2954Reputation: 2954
Quote:
Originally Posted by Disillusionist View Post
As previously stated by colucix, it is not accurate to replace all instances of 'b' in a file name.
Same goes for Jschiwal's solution: splitting filepath and filename (filepath="${item%/*}"; filename="${item//*\//}") and only working on filename should work.
 
Old 11-10-2007, 05:57 AM   #9
jschiwal
Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 655Reputation: 655Reputation: 655Reputation: 655Reputation: 655Reputation: 655
I just showed a way of changing the filename without taking the directories into account, to show what variable substition looks like. Since the directories don't contain the letter "b" and are all one level deep, you could cheat a bit like:
Code:
ls -R
.:
2004-12-24  2005-06-11  2006-06-25  2006-10-21

./2004-12-24:
100_0156.jpg

./2005-06-11:
100_1643.jpg

./2006-06-25:
100b0042.jpg

./2006-10-21:
100_4940.jpg  100b4880.jpg  100b5006.jpg  100b5054.jpg
jschiwal@hpmedia:~/junk> for file in */*.jpg; do
> mv "${file}" "${file//b/_}" -v
> done
mv: `2004-12-24/100_0156.jpg' and `2004-12-24/100_0156.jpg' are the same file
mv: `2005-06-11/100_1643.jpg' and `2005-06-11/100_1643.jpg' are the same file
`2006-06-25/100b0042.jpg' -> `2006-06-25/100_0042.jpg'
mv: `2006-10-21/100_4940.jpg' and `2006-10-21/100_4940.jpg' are the same file
`2006-10-21/100b4880.jpg' -> `2006-10-21/100_4880.jpg'
`2006-10-21/100b5006.jpg' -> `2006-10-21/100_5006.jpg'
`2006-10-21/100b5054.jpg' -> `2006-10-21/100_5054.jpg'
In this particular case, since only one "b" is found in the name, you could use "${file/b/_}" for the target. Two clashes would substitute all the "b"'s in the pathname.

Last edited by jschiwal; 11-10-2007 at 05:59 AM.
 
Old 11-10-2007, 07:06 AM   #10
matthewg42
Senior Member
 
Registered: Oct 2003
Location: UK
Distribution: Kubuntu 12.10 (using awesome wm though)
Posts: 3,530

Rep: Reputation: 63
Quote:
Originally Posted by tmbigrigg View Post
When I run the command
Code:
find /media/hdb6/200* -type f |xargs rename -n 'tr/b/_/g'
I am getting the following returned to me:

Code:
Bareword found where operator expected at (eval 1) line 1, near "tr/b/_/g"
syntax error at (eval 1) line 2, near "tr/b/_/g
"
xargs: rename: exited with status 255; aborting
Ah, my silly mistake. I originally did it like this:
Code:
rename 's/b/_/g'
But then changed the s to a tr. The operations work slightly differently (although achieve the same thing). I wanted to use tr because it is simpler, and I hoped that if you looked up what it was doing it would be clearer. I forgot to remove the g option on the end, which has no meaning for tr. Please amend the command like this:
Code:
find /media/hdb6/200* -type f |xargs rename -n 'tr/b/_/'
 
Old 11-10-2007, 08:02 AM   #11
Disillusionist
Senior Member
 
Registered: Aug 2004
Location: England
Distribution: Ubuntu
Posts: 1,013

Rep: Reputation: 83
The -n option on rename will show the files that would be changed.

Once you are happy that they are right, remove the -n option to make the change.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Bash script to remove capitalisation and spaces form a filename scuzzman Programming 11 05-18-2008 01:28 PM
changing path from a bash script ggeeoo Linux - Newbie 7 01-04-2006 07:35 PM
Getting the first part of a filename in a BASH script trevelluk Programming 3 02-15-2005 02:06 AM
Bash script to change a filename associated with an inode index number. Ziv Programming 22 06-19-2004 09:41 AM
bash script - incrementing a filename in a script tslinux Programming 10 08-06-2003 12:58 AM


All times are GMT -5. The time now is 11:13 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration