LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
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 06-18-2004, 04:52 PM   #16
Muzzy
Member
 
Registered: Mar 2004
Location: Denmark
Distribution: Gentoo, Slackware
Posts: 333

Rep: Reputation: 30
I'll have another BASH at this :)


Hello again,

I have had another go at this one....

Using find might not work because if you change the names of some directories half way through the search, I guess it can confuse find, possibly missing some files, therefore if you want a recursive algorithm, you should use a script with a for loop.

DISCLAIMER: I am not a bash expert... I am still learning every day. I have done a small amount of testing on this script and it seems to work on the few test cases I have tried, but recursive scripts that modify the filesystem are powerful tools to be used with care, so don't run this as root, and if the data is important, back it up first. If there are problems though, I will be happy to try to fix them, but I can't recover any lost data!

Code:
bad='[^A-Za-z0-9_.-]'

f() {
for i in *
do
  echo $i | grep $bad &&
    new=`echo $i | sed s/$bad/_/g` && mv -i "$i" "$new" &&
    i=$new
  [ -d $i ] && [ ! -s $i ] cd $i && f && cd ..
done
}

f
Description: the first line specifies which characters are not allowed. Next a function f() is declared. This function lists all the files and directories in the pwd. It then greps each filename $i to see if it contains a bad character. If so, it calculates $new (the new filename), performs a move (asks before overwriting), and then updates $i to the new name. Then it checks if $i is a directory (but skip symbolic links) and if so, cd's into the directory and calls itself recursively. By skipping symbolic links, it hopefully won't go into an infinite loop, but I may have overlooked something. The last line calls the function that was jsut declared, starting at the current directory.

I used && instead of ;'s and if fi blocks. You may find this hard to read. Sorry! I'm sure this code could be cleaned up a bit and it can definitely be made more readable! Improvements are very welcome, I would be happy to see alternative ways to do this.

I hope this is at least be something you can work from. Let me know how you get on.

Happy Bashing!
Mark.
 
Old 06-18-2004, 05:49 PM   #17
Ziv
LQ Newbie
 
Registered: May 2004
Location: WA
Distribution: RedHat 7.3/9/ES
Posts: 13

Original Poster
Rep: Reputation: 0
Thank you I will give it a try...

I will let you know how it goes...

Thank you for your help putting this together.

Ziv
 
Old 06-18-2004, 08:12 PM   #18
Ziv
LQ Newbie
 
Registered: May 2004
Location: WA
Distribution: RedHat 7.3/9/ES
Posts: 13

Original Poster
Rep: Reputation: 0
I think I got it!!!

Well this seems to work for me, with some modifications...

Here is the code I created based off of your help.

Code:
#!/bin/bash

badnames=`find -name '*[;"\\=?()<>&*|$]*'`

for x in $badnames
do
  new=`echo $x | sed 's/[{;"\\=?()<>&*|$]/_/g'`
  echo $x 
  echo $new
  mv -i "$x" "$new"
done
It worked perfectly on a 3 level deep directory.

Do you see any problems with this method?

Ziv
 
Old 06-18-2004, 09:32 PM   #19
Ziv
LQ Newbie
 
Registered: May 2004
Location: WA
Distribution: RedHat 7.3/9/ES
Posts: 13

Original Poster
Rep: Reputation: 0
Angry It is not working perfectly...

Dang!

It doesn't handle spaces in directory names.

Well... any other ideas?

Ziv
 
Old 06-19-2004, 07:47 AM   #20
Muzzy
Member
 
Registered: Mar 2004
Location: Denmark
Distribution: Gentoo, Slackware
Posts: 333

Rep: Reputation: 30
What error did you get?

As I tried to point out in my earlier post, I don't think you should use find if you are going to be renaming the directories, since this will cause lots of file not found errors once you have renamed the parent directories (NOTE: I reconsidered this again, and now i have decided that if you make sure that you rename the deepest file first, maybe you can get this to work! I will experiment with this).

Your problem with spaces is because the way 'for' works on a variable, splitting at the spaces. Although I'm sure there is a way to fix this, you will still end up with the problem with find I mention above.

To avoid both these problems, I would advise using the 'for i in *' method, as I did in my example, and iterating through the directories manually. I have no idea what problem you encountered. Perhaps I didn't explain well enough how to use the script? Or perhaps you have something in your directory structure that I hadn't thought of (sockets / hard links / some feature I've never heard of / a strange character that causes my script to fail).

If you could explain to me exactly what didn't work wiht my script, I am sure I can fix the problem. Ideally, post a script which creates a directory structure for which my proposed renaming script fails such as
Code:
mkdir 'foo bar'; touch 'foo bar/baz';
Also post the error message you get. Then I can run it on my computer to reproduce the error, and work out how to fix it. It is much easier for me to fix an error if it is reproducable on my computer.

Mark.
 
Old 06-19-2004, 07:54 AM   #21
Muzzy
Member
 
Registered: Mar 2004
Location: Denmark
Distribution: Gentoo, Slackware
Posts: 333

Rep: Reputation: 30
I found an error in my script! The last minute change I did to ignore softlinks was incorrect in the example I posted! (I missed a &&)

Code:
bad='[^A-Za-z0-9_.-]'

f() {
for i in *
do
  echo $i | grep $bad &&
    new=`echo $i | sed s/$bad/_/g` && mv -i "$i" "$new" &&
    i=$new
  [ -d $i ] && [ ! -s $i ] && cd $i && f && cd ..
done
}

f
If this doesn't work for you, please post the error!
 
Old 06-19-2004, 08:18 AM   #22
Muzzy
Member
 
Registered: Mar 2004
Location: Denmark
Distribution: Gentoo, Slackware
Posts: 333

Rep: Reputation: 30
OK there are problems with my script too! First the test for a symbolic link is -h, and not -s. Second, it looks like the values of local variables are not restored to their original values on returning from a function call.... perhaps it is possible to specify variables as local somehow. I'll look at this now and get back to you later when I have an answer.
 
Old 06-19-2004, 08:41 AM   #23
Muzzy
Member
 
Registered: Mar 2004
Location: Denmark
Distribution: Gentoo, Slackware
Posts: 333

Rep: Reputation: 30
Script version 3 :

Code:
bad='[^A-Za-z0-9_.-]'

f() {
for i in *
do
  j=$i
  echo $i | grep $bad && { j=`echo $j | sed s/$bad/_/g`; mv -i "$i" $j; }
  [ -d $j ] && [ ! -h $j ] && { cd $j; f;  cd ..; }
done
}

f
Test: (assumption: script exists in the current directory and is called 'renamebad')

Code:
$ mkdir 'a b'; touch 'a b/c d'; sh renamebad
Expected result:

Code:
$ ls -R
.:
a_b  renamebad
 
./a_b:
c_d
Have a go with this! Slightly better tested than my first effort.
 
  


Reply



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 Array index value Kedelfor Programming 10 04-29-2009 04:37 AM
iNode number, how does it change? saudoi Solaris / OpenSolaris 4 05-22-2005 04:38 AM
Getting the first part of a filename in a BASH script trevelluk Programming 3 02-15-2005 01:06 AM
What can change an inode number? nc101 Linux - General 2 01-03-2005 10:29 AM
bash script - incrementing a filename in a script tslinux Programming 10 08-05-2003 11:58 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:42 PM.

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
Open Source Consulting | Domain Registration