modifying case of dirs and files name
Web Server forum
Back To The Forum Home!Search!Private Messaging System

Web Server Talk Web Server Talk > Unix and Linux reviews > Free Unix support > Unix Shell > modifying case of dirs and files name




Pages (3): [1] 2 3 »   Last Thread   Next Thread Next
  Show Printable Version Email this Page Subscribe to this Thread      Post New Thread    Post A Reply      

    modifying case of dirs and files name  
elerdin


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-22-06 11:10 PM

Hallo, I'm trying to recursively change the case of names of files and
subdirs into a directory using bash, I created some nested directrories
with some
files:

$ find . -depth
./prova.sh
./pollo/pippo/prova2
./pollo/pippo/pluto
./pollo/pippo
./pollo/prova1
./pollo/prova con spazi
./pollo
.

and this script:

###
#! /bin/bash

lista=( $(find . -depth | sed "s/ /_/g" | sed "s/^\.//g" | sed
"s/^\///g") )

for i in $(seq 0 $((${#lista[@]} - 1)))
do
percorso=`echo '"'`${lista[$i]}`echo '"'` # for managing spaces

dir=`dirname $percorso`
base=`basename $percorso`

mv `echo $percorso | sed "s/_/ /g"` `echo $dir | sed "s/_/
/g"``echo "/"``echo $base | sed "s/_/ /g" | tr [:lower:] [:upper:] |
sed "s/_/ /g"`

done

###

but it returns:

mv: cannot stat `"prova.sh"': No such file or directory
mv: cannot stat `"pollo/pippo/prova2"': No such file or directory
mv: cannot stat `"pollo/pippo/pluto"': No such file or directory
mv: cannot stat `"pollo/pippo"': No such file or directory
mv: cannot stat `"pollo/prova1"': No such file or directory
mv: when moving multiple files, last argument must be a directory
Try `mv --help' for more information.
mv: cannot stat `"pollo"': No such file or directory

If I echo the command-line created by the script and it seems to be ok
and if I copy and paste it on the shell it works, so I suppose the
problem is how bash manage something into the command I create.

Has someone any suggestion?

Thanks, Elerdin.






[ Post a follow-up to this message ]



    Re: modifying case of dirs and files name  
Dave Kelly


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-22-06 11:10 PM

elerdin wrote:
> Hallo, I'm trying to recursively change the case of names of files and
> subdirs into a directory using bash, I created some nested directrories
> with some
> files:
>
>te it on the shell it works, so I suppose the
> problem is how bash manage something into the command I create.
>
> Has someone any suggestion?
>
> Thanks, Elerdin.
>
Unless you need to reinvent the wheel for a homework assignment or
something, investigate the power of 'tr'. There is a manual and/or find
a copy of  'Linux in a Nutshell' online and peruse their examples.





[ Post a follow-up to this message ]



    Re: modifying case of dirs and files name  
Ed Morton


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-22-06 11:10 PM

elerdin wrote:
> Hallo, I'm trying to recursively change the case of names of files and
> subdirs into a directory using bash, I created some nested directrories
> with some
> files:
>
> $ find . -depth
> ./prova.sh
> ./pollo/pippo/prova2
> ./pollo/pippo/pluto
> ./pollo/pippo
> ./pollo/prova1
> ./pollo/prova con spazi
> ./pollo
> .
>
> and this script:
>
> ###
> #! /bin/bash
>
> lista=( $(find . -depth | sed "s/ /_/g" | sed "s/^\.//g" | sed
> "s/^\///g") )
>
> for i in $(seq 0 $((${#lista[@]} - 1)))
> do
>         percorso=`echo '"'`${lista[$i]}`echo '"'` # for managing 
spaces
>
>         dir=`dirname $percorso`
>         base=`basename $percorso`
>
>         mv `echo $percorso | sed "s/_/ /g"` `echo $dir | sed "s/_/
> /g"``echo "/"``echo $base | sed "s/_/ /g" | tr [:lower:] [:upper:]
 |
> sed "s/_/ /g"`
>
> done
>
> ###

Well, you certainly did attempt it first! It's not 100% clear what the
above is attempting to do or what your requirements are, so try this first:

find . -print | while IFS= read -r dirfile
do
srcDir="${dirfile%/*}"
srcFile="${dirfile##*/}"
destDir=`echo "$srcDir" | tr '[a-z]' '[A-Z]'`
destFile=`echo "$srcFile" | tr '[a-z]' '[A-Z]'`
echo "a) ${srcDir}/${srcFile} -> ${destDir}/${destFile}"
echo "b) ${srcDir}/${srcFile} -> ${srcDir}/${destFile}"
done

and tell us which of the transformations, a or b, if any, is what you
actually want. If neither, what do you want? It would also be useful to
know which shell you're using.

Ed.





[ Post a follow-up to this message ]



    Re: modifying case of dirs and files name  
Michael Paoli


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-22-06 11:10 PM

elerdin wrote:
> Hallo, I'm trying to recursively change the case of names of files and
> subdirs into a directory using bash, I created some nested directrories
>
> #! /bin/bash
> lista=( $(find . -depth | sed "s/ /_/g" | sed "s/^\.//g" | sed
> "s/^\///g") )
> for i in $(seq 0 $((${#lista[@]} - 1)))
> do
>         percorso=`echo '"'`${lista[$i]}`echo '"'` # for managing 
spaces
>         dir=`dirname $percorso`
>         base=`basename $percorso`
>         mv `echo $percorso | sed "s/_/ /g"` `echo $dir | sed "s/_/
> /g"``echo "/"``echo $base | sed "s/_/ /g" | tr [:lower:] [:upper:]
 |
> sed "s/_/ /g"`
> done
>
> mv: cannot stat `"prova.sh"': No such file or directory
> mv: when moving multiple files, last argument must be a directory
>
> If I echo the command-line created by the script and it seems to be ok
> and if I copy and paste it on the shell it works, so I suppose the
> problem is how bash manage something into the command I create.

Study the Frequently Asked Questions (FAQ), most notably 2.6):
Message-ID: <unix-faq/faq/part2_1136785841@rtfm.mit.edu>
http://groups.google.com/group/comp...c76fcc5a70422db

(Re)read and study the bash(1) manual pages, most notably the sections
on echo, quoting, and command substitution.

references/excerpts:
Message-ID: <unix-faq/faq/part2_1136785841@rtfm.mit.edu>
http://groups.google.com/group/comp...c76fcc5a70422db
bash(1) *
test(1) *
[(1) *
expr(1) *
echo(1) *
ksh(1) *
sh(1) *
tr(1)
sed(1)
perl(1)
* note that in many cases, many of these utilities also exist as
built-ins for many of the more modern shells and implementations
thereof.






[ Post a follow-up to this message ]



    Re: modifying case of dirs and files name  
elerdin


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-22-06 11:10 PM

Thanks, to all for your fast answers, but all solutions you're
suggesting cover simplier case only. I'm using bash. The script is for
changing the case of both names of files and names of directory
recursively and must manage spaces in names.

I hope I can explain better, I have this directory structure:

./DIR1/DIR2/DIR3/FILE3.TXT
./DIR1/DIR2/DIR3
./DIR1/DIR2/FILE2.TXT
./DIR1/DIR2
./DIR1/FILE WITH SPACES.TXT
./DIR1/FILE1.TXT
./DIR1

I want to obtain this:

./dir1/dir2/dir3/file3.txt
./dir1/dir2/dir3
./dir1/dir2/file2.txt
./dir1/dir2
./dir1/file with spaces.txt
./dir1/file1.txt
./dir1

I create that script, but I do not understand why it does not work. I
post another time the script:

###
#! /bin/bash

list=( $(find . -depth | sed "s/ /_/g") )

for i in $(seq 0 $((${#list[@]} - 1)))
do
fullpath=`echo '"'`${list[$i]}`echo '"'`

dir=`dirname $fullpath`
base=`basename $fullpath`

echo "mv "`echo $fullpath | sed "s/_/ /g"`" "`echo $dir | sed "s/_/
/g"``echo "/"``echo $base | sed "s/_/ /$done

###

As you can see the "mv" line, the last one, is echoed, the command it
output are all correct, and if I put the into a file and execute that
file all works fine, but I do not understand why the same commands do
not work INSIDE the script. The problem is  the "mv" line for sure, but
I do not understan where, probably the bash does something I do not
understand.

Thanks, Elerdin.






[ Post a follow-up to this message ]



    Re: modifying case of dirs and files name  
Stachu 'Dozzie' K.


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-22-06 11:10 PM

On 22.01.2006, elerdin <elerdin@gmail.com> wrote:
> Thanks, to all for your fast answers, but all solutions you're
> suggesting cover simplier case only. I'm using bash. The script is for
> changing the case of both names of files and names of directory
> recursively and must manage spaces in names.
>
> I hope I can explain better, I have this directory structure:
>
> ./DIR1/DIR2/DIR3/FILE3.TXT
> ./DIR1/DIR2/DIR3
> ./DIR1/DIR2/FILE2.TXT
> ./DIR1/DIR2
> ./DIR1/FILE WITH SPACES.TXT
> ./DIR1/FILE1.TXT
> ./DIR1
>
> I want to obtain this:
>
> ./dir1/dir2/dir3/file3.txt
> ./dir1/dir2/dir3
> ./dir1/dir2/file2.txt
> ./dir1/dir2
> ./dir1/file with spaces.txt
> ./dir1/file1.txt
> ./dir1
>
> I create that script, but I do not understand why it does not work.

Actually, I don't understand why do you expect it to work correctly.
It's too complicated for such simple task.

> As you can see the "mv" line, the last one, is echoed, the command it
> output are all correct, and if I put the into a file and execute that
> file all works fine, but I do not understand why the same commands do
> not work INSIDE the script. The problem is  the "mv" line for sure, but
> I do not understan where,

Nope. The problem is not in the line with mv. The problem is in your
whole script. It's one big mess. Let me explain:

> #! /bin/bash
>
> list=( $(find . -depth | sed "s/ /_/g") )

What would it do if name of some directory with files contains spaces?
Another thing, let's assume you don't have dirs with spaces. How would
you rename './ble/file with spaces.txt'? You would only get
'./ble/file_with_spaces.txt'.

> for i in $(seq 0 $((${#list[@]} - 1)))
> do

What is that `seq` for? Do you really need the index of current array
element? Let me guess: you have some programming experience in C or
Pascal and nothing of higher level, right? In most scripting languages
(and many compiled ones) an array is a list and you can move through
whole list using element by element. This is the correct way to process
each element in bash:
#v+
for element in "${list[@]}"; do
#v-

>         fullpath=`echo '"'`${list[$i]}`echo '"'`

What are all these quote characters for? Explain it[*]. And then,
rewrite this assignment.

>         dir=`dirname $fullpath`
>         base=`basename $fullpath`

If $fullpath contains in some magical way spaces, then how would dirname
react? And basename? Another matter is the $fullpath will never contain
spaces, but names of your files will do.

> echo "mv "`echo $fullpath | sed "s/_/ /g"`" "`echo $dir | sed "s/_/
> /g"``echo "/"``echo $base | sed "s/_/ /$done

Ouch. Too many `echo|sed's and misused quote characters for me.
Again, try to explain every single quote character[*].


Last of all, I'll use "find ... | PERL -e '...'", since PERL is able to
manipulate filenames and then rename files without exec()ing lots of
processes, which would speed up the command significantly for large
number of files (>500). And yes, I did use `find|perl' this way.


[*] I really mean "explain". What it should it do? And what it is
actually doing? I know from experience that this helps very much in
understanding explained thing.

--
Feel free to correct my English
Stanislaw Klekot





[ Post a follow-up to this message ]



    Re: modifying case of dirs and files name  
Ed Morton


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-23-06 01:58 AM

elerdin wrote:
> Thanks, to all for your fast answers, but all solutions you're
> suggesting cover simplier case only. I'm using bash. The script is for
> changing the case of both names of files and names of directory
> recursively and must manage spaces in names.
>
> I hope I can explain better, I have this directory structure:
>
> ./DIR1/DIR2/DIR3/FILE3.TXT
> ./DIR1/DIR2/DIR3
> ./DIR1/DIR2/FILE2.TXT
> ./DIR1/DIR2
> ./DIR1/FILE WITH SPACES.TXT
> ./DIR1/FILE1.TXT
> ./DIR1
>
> I want to obtain this:
>
> ./dir1/dir2/dir3/file3.txt
> ./dir1/dir2/dir3
> ./dir1/dir2/file2.txt
> ./dir1/dir2
> ./dir1/file with spaces.txt
> ./dir1/file1.txt
> ./dir1


That's just this:

find . -print | while IFS= read -r src
do
dest=`echo "$src" | tr '[A-Z]' '[a-z]'`
srcDir="${src%/*}"
destDir="${dest%/*}"
mkdir -p "$destDir"
mv "$src" "$dest"
done

Regards,

Ed.





[ Post a follow-up to this message ]



    Re: modifying case of dirs and files name  
Michael Paoli


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-23-06 07:55 AM

elerdin wrote:
> Thanks, to all for your fast answers, but all solutions you're
> suggesting cover simplier case only. I'm using bash. The script is for
> changing the case of both names of files and names of directory
> recursively and must manage spaces in names.

Maybe you didn't have a chance to see what I'd posted earlier.  Didn't
exactly spell out a full answer, but provided hints and pointers to the
essential information resources:
Message-ID: <1137952831.100858.131330@g44g2000cwa.googlegroups.com>
http://groups.google.com/group/comp...7909944d4615bdb
I suggest studying that stuff (totally unbiased opinion, of course).
;-)

> I hope I can explain better, I have this directory structure:
> ./DIR1/DIR2/DIR3/FILE3.TXT
> ./DIR1/DIR2/DIR3
> ./DIR1/DIR2/FILE2.TXT
> ./DIR1/DIR2
> ./DIR1/FILE WITH SPACES.TXT
> ./DIR1/FILE1.TXT
> ./DIR1
> I want to obtain this:
> ./dir1/dir2/dir3/file3.txt
> ./dir1/dir2/dir3
> ./dir1/dir2/file2.txt
> ./dir1/dir2
> ./dir1/file with spaces.txt
> ./dir1/file1.txt
> ./dir1

> I create that script, but I do not understand why it does not work. I
> post another time the script:

> #! /bin/bash
> list=( $(find . -depth | sed "s/ /_/g") )
> for i in $(seq 0 $((${#list[@]} - 1)))
> do
>         fullpath=`echo '"'`${list[$i]}`echo '"'`
>         dir=`dirname $fullpath`
>         base=`basename $fullpath`
> echo "mv "`echo $fullpath | sed "s/_/ /g"`" "`echo $dir | sed "s/_/
> /g"``echo "/"``echo $base | sed "s/_/ /$done

> As you can see the "mv" line, the last one, is echoed, the command it
> output are all correct, and if I put the into a file and execute that
> file all works fine, but I do not understand why the same commands do
> not work INSIDE the script. The problem is  the "mv" line for sure, but
> I do not understan where, probably the bash does something I do not
> understand.

Okay, ... how about some more hints and a potentially useful example:

$ find DIR1 -print
DIR1
DIR1/DIR2
DIR1/DIR2/DIR3
DIR1/DIR2/DIR3/FILE3.TXT
DIR1/DIR2/FILE2.TXT
DIR1/FILE1.TXT
DIR1/FILE WITH SPACES.TXT
$ ./lcase
$ find dir1 -print
dir1
dir1/dir2
dir1/dir2/dir3
dir1/dir2/dir3/file3.txt
dir1/dir2/file2.txt
dir1/file with spaces.txt
dir1/file1.txt
$ cat lcase
#!/bin/sh
find . -depth -name '*[A-Z]*' -exec bash -c '
t="`echo -nE '''{}''' | sed -e '''s![^/]*$!\L&!'''`"
if [ -a "$t" ] || [ -h "$t" ]; then
1>&2 echo "$0: $t already exists"
else
mv -f '''{}''' "$t"
fi
' \;
$

If one carefully studies bash(1), particularly all the quoting and
command substitution stuff and also the echo and test ([) built-in
to bash(1), and also find(1), sed(1) and mv(1), the above example
should all start to make lots of sense (as should why your earlier
example didn't achieve what you wanted).

And extra credit: The example I wrote won't work perfectly in all
cases.  Find one or more flaws or potential unexpected behaviors (e.g.
where it won't precisely and only change the case of the the
filename/directory).

And at least some possible extra credit answers/hints (rot13(6)):
genvyvat arjyvar(f)
anzr pbyyvfvba grfgvat naq genvyvat arjyvar(f)
rkvg inyhr beqre qrcraqrapl






[ Post a follow-up to this message ]



    Re: modifying case of dirs and files name  
Stephane CHAZELAS


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-23-06 07:55 AM

2006-01-22, 11:57(-08), elerdin:
> Thanks, to all for your fast answers, but all solutions you're
> suggesting cover simplier case only. I'm using bash. The script is for
> changing the case of both names of files and names of directory
> recursively and must manage spaces in names.
>
> I hope I can explain better, I have this directory structure:
>
> ./DIR1/DIR2/DIR3/FILE3.TXT
> ./DIR1/DIR2/DIR3
> ./DIR1/DIR2/FILE2.TXT
> ./DIR1/DIR2
> ./DIR1/FILE WITH SPACES.TXT
> ./DIR1/FILE1.TXT
> ./DIR1
>
> I want to obtain this:
>
> ./dir1/dir2/dir3/file3.txt
> ./dir1/dir2/dir3
> ./dir1/dir2/file2.txt
> ./dir1/dir2
> ./dir1/file with spaces.txt
> ./dir1/file1.txt
> ./dir1
[...]

Use zsh:

autoload -U zmv # if not already in your ~/.zshrc
zmv '(**/)(*)' '$1${(L)2}'


--
Stéphane





[ Post a follow-up to this message ]



    Re: modifying case of dirs and files name  
Xicheng


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-23-06 11:13 PM

elerdin wrote:
> Thanks, to all for your fast answers, but all solutions you're
> suggesting cover simplier case only. I'm using bash. The script is for
> changing the case of both names of files and names of directory
> recursively and must manage spaces in names.

The problem could be easier if you handle files and directories
separately.

#changing files:
find -type f | PERL -nle 'm#[a-z]+[^/]*$# and m#^(.*/)(.*?)$# and pr
int
"mv \"$_\" \"$1\U$2\""' | sh

1) use PERL to separate filename with dirname, and print out only
filenames containing at least one lower-case character. then print out
in the following form:
m#[a-z]+[^/]*$#  ---> at least one [a-z] in filename
m#^(.*/)(.*?)$# --> separate filename with dirname
print "mv \"$_\" \"$1\U$2\""'  --> printout mv "$oldname" "$newname"

use quotes to enclose two arguments of "mv", which can solve the
problem of spaces in the filename/dirname.

#changing directories
find -type d | tac | PERL -nle 'm#[a-z]+[^/]*$# and m#^(.*/)(.*?)$# 
and
print "mv \"$_\" \"$1\U$2\""' | sh

2) when operating on directories, use "tac" to reverse the output of
"find", and each time you change only the rightmost subdirectory. This
way you wouldnt get complained because you won't change the name of
parent-directory before that of sub-directory...

HTH,
Xicheng

> I hope I can explain better, I have this directory structure:
>
> ./DIR1/DIR2/DIR3/FILE3.TXT
> ./DIR1/DIR2/DIR3
> ./DIR1/DIR2/FILE2.TXT
> ./DIR1/DIR2
> ./DIR1/FILE WITH SPACES.TXT
> ./DIR1/FILE1.TXT
> ./DIR1
>
> I want to obtain this:
>
> ./dir1/dir2/dir3/file3.txt
> ./dir1/dir2/dir3
> ./dir1/dir2/file2.txt
> ./dir1/dir2
> ./dir1/file with spaces.txt
> ./dir1/file1.txt
> ./dir1
>
> I create that script, but I do not understand why it does not work. I
> post another time the script:
>
> ###
> #! /bin/bash
>
> list=( $(find . -depth | sed "s/ /_/g") )
>
> for i in $(seq 0 $((${#list[@]} - 1)))
> do
>         fullpath=`echo '"'`${list[$i]}`echo '"'`
>
>         dir=`dirname $fullpath`
>         base=`basename $fullpath`
>
> echo "mv "`echo $fullpath | sed "s/_/ /g"`" "`echo $dir | sed "s/_/
> /g"``echo "/"``echo $base | sed "s/_/ /$done
>
> ###
>
> As you can see the "mv" line, the last one, is echoed, the command it
> output are all correct, and if I put the into a file and execute that
> file all works fine, but I do not understand why the same commands do
> not work INSIDE the script. The problem is  the "mv" line for sure, but
> I do not understan where, probably the bash does something I do not
> understand.
>
> Thanks, Elerdin.






[ Post a follow-up to this message ]



    Sponsored Links  




 





   All times are GMT. The time now is 09:06 PM.      Post New Thread    Post A Reply      
Pages (3): [1] 2 3 »   Last Thread   Next Thread Next


Most Popular forums 

Forum Jump:
Rate This Thread:

Forum Rules:
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is OFF
vB code is ON
Smilies are ON
[IMG] code is OFF
 
Medical and Health forum | Computer Games Reviews | Graphics design forum

Back To The Top
Home | Usercp | Faq | Register