[comp.unix.questions] SUMMARY: Mapping of Directory names to lower case

donald@control.eng.glasgow.ac.uk (Donald Ballance) (04/25/91)

SUMMARY: Re: Mapping of Directory names to lower case


My original posting was:

>  I have a need to be able to get a list of a directory tree and a
>  lowercase version of it; this is so that the directory can be
>  selected in a case insensitive manner, i.e., they can specify
>  contents/info and get information on contents/INFO.
> 
>  What I would like is a file with:
>  lowercase_directory_name Upper_Case_directory_name
>  an immaginary example would be:
> 
>  contents             contents
>  contents/data        contents/Data
>  contents/info        contents/INFO
>  contents/users       contents/users
>  contents/users/big   contents/users/BIG
>  contents/users/small contents/users/SMALL
> 
>  I would like to do this with standard Unix utilities (i.e., awk, sh,
>  tr, etc.) if possible.  Please mail me directly as I don't have time
>  to read this newsgroup.  I'll summarize back to the mailing list.
>  I'm using a SunOS 4.1.
> 
>  Thanks in advance
> 
>  Donald Ballance
 
First I must appologise as, although I though I'd put the problem
clearly I obviously hadn't.  My requirement was to produce the list
I had given as an example.

Many people confimed my impression that the best way to get one
copy of the list was through using find, in particular the command

find . -type d -print

is seems to be the best method of producing the directory list.

The real problem was to create a file with both the lower and upper
versions such that a user could specify the directory, I could run it
through tr A-Z a-z to produce a lower case version, and then use
a shell script like that below to select the correct directory.

for j in $*
do
    Dir="$j";
    case $j in
	contents)		Dir="contents
	contents/data)		Dir="contents/Data
	contents/info)		Dir="contents/INFO
	contents/users)		Dir="contents/users
	contents/users/big)	Dir="contents/users/BIG
	contents/users/small)	Dir="contents/users/SMALL
        .) Dir="unknown";;
    esac
 .
 .
 .
done



The commands that I had missed out on were the use of 'pr', 'paste',
and the use of 'sed' to process only the first word. Also the technique
of using awk to translate \012 <CR> to space was interesting.

I haven yet tried out all of the ideas but a number of them definitely
work.  Full responses are given below.

Thanks to:
Brian Fitzgerald <fitz@edu.rpi.meche.mml0>
Tony Rems <rembo@com.unisoft>
Jonathan "I." Kamens <jik@edu.MIT.pit-manager>
Luiz Henrique de Figueiredo <LHFIG@EARN.BRLNCC>
John Gordon <gordon@edu.uiuc.cso.osiris>
dkeisen@edu.Stanford.Gang-of-Four (Dave Eisen)
I.Sparry@uk.ac.bath.gdt
jpolcari@com.prime.cat (Joe Polcari x4489)
Jennifer "H." Zemsky <jhz@edu.columbia.cc.cunixa>
andy@com.icom.xwkg (Andrew H. Marrinson)
allbery@org.NCoast (Brandon S. Allbery KB8JRR/AA)
Alan Thew <qq11@uk.ac.liverpool.uxb>
"Ehud Reshef  edr@techunix.technion.ac.il" <edr@IL.AC.TECHNION.CARMEL>
Perry Statham <perry%statham@edu.utexas.cs>
Jean-Marc_de_chez_Hackers_alias_ <edgard@fr.gipsi.cao>
Braham Levy <pha21@uk.ac.keele.seq1>
pfinkel@com.att.oac (Paul D Finkel)


-----------------------------------------------------------------------------
From: Brian Fitzgerald <fitz@edu.rpi.meche.mml0>

If you just want to list a lower case version of anything, pipe it
through tr with the appropriate arguments.  If really want to store
this duplicate information in a file somewhere, then you can use tr and
awk to accomplish that, but before long the file will be out of date.

However, if, as you say, you want to be able to "select" something in a
case insensitive manner then echo the thing, pipe it through tr,
enclose it in back quotes, and use the rresult as part of a command.

For example, in a c shell, to cd to a directory in a case insensitive manner
try this alias.

[12] mml0 % alias cd 'cd `echo \!:1 | tr "[A-Z" "[a-z]"`'
[13] mml0 % cd BIN
[14] mml0 % pwd
/home/staff/fitz/bin

Use the backquoting scheme in a shell script somehow to accomplish
what you are really trying to do.

This works for Sun OS, but /usr/5bin/echo and /usr/5bin/tr behaves
differently from /bin/echo and/bin/tr

Brian

-----------------------------------------------------------------------------
From: Tony Rems <rembo@com.unisoft>

If you're just going to put the names into a file,
then use grep -i.  This does case insensitive pattern matching.

Or if you really must have it this way, then do a 
find . -print | tr '[A-Z]' '[a-z]' 

-Tony

-----------------------------------------------------------------------------
From: Jonathan "I." Kamens <jik@edu.MIT.pit-manager>

  Personally, I would do this with perl, because I *know* that perl has all of
the necessary features, including the ability to do what "find" does and the
ability to convert upper-case to lowercase.

  You could also do it with awk, if you could figure out in awk how to convert
upper-case to lowercase, and this is, indeed, possible, if you have a version
of awk that does functions.  This has been discussed on the net in the past.

  However, if you don't want to use perl and don't want to figure out how to
do tr conversions in awk (or don't have an awk that supports functions), you
can do something like this:

#!/bin/sh

find "$1" -type d -print | while read dir ; do
	echo `echo "$dir" | tr '[A-Z]' [a-z]'` "$dir"
done 

Now, for efficienty, I would replace echo with /bin/echo and tr with /bin/tr
unless your shell has either of these builtin (the former is possible, the
latter unlikely).

  This doesn't put the directory names in even columns; if that's necessary,
you can pipe the output of the loop through awk to do that, like this:

#!/bin/sh

find "$1" -type d -print | while read dir ; do
	echo `echo "$dir" | tr '[A-Z]' [a-z]'` "$dir"
done | awk '{printf("%-30s %-30s\n", $1, $2)}'

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

-----------------------------------------------------------------------------
From: Luiz Henrique de Figueiredo <LHFIG@EARN.BRLNCC>

Assuming you already have the filename list called l, try:
 
 tr A-Z a-z <l | paste - l
 
A list can be obtained using find.
 
----------------------------------------------------------------------
Luiz Henrique de Figueiredo                        lhfig@brlncc.bitnet
IMPA/CNPq                                          lhfu@lncc.bitnet
Estrada Dona Castorina 110
22460 Rio de Janeiro, RJ, Brasil                   (021) 294-9032 r226
----------------------------------------------------------------------

-----------------------------------------------------------------------------
From: John Gordon <gordon@edu.uiuc.cso.osiris>


	You could probably do a lot of this with a `ls -RC | grep "\/"' (to
recursively print all files and strip out directories) and "tr". (to
translate upper to lower.  do a "man tr" to learn more.)


---
John Gordon
Internet: gordon@osiris.cso.uiuc.edu        #include <disclaimer.h>
          gordon@cerl.cecer.army.mil       #include <clever_saying.h>

-----------------------------------------------------------------------------
From: dkeisen@edu.Stanford.Gang-of-Four (Dave Eisen)
To: donald

This isn't pretty (it forks a new process for every file in the directory
tree), but it's a start:

:
# Shell program to output a list of files on a system in the form
# lowercase_filename	actual_filename

find / -print |
	while read file
	do
		echo $file | tr "[A-Z\012]" "[a-z	]"
		echo $file
	done

where the tr command takes upper case letters and makes them lower case
and converts newlines to tabs.

I hope you can do better than this.




-- 
Dave Eisen                      
1101 San Antonio Rd. Suite 102    
Mountain View, CA 94043                   
(415) 967-5644                   dkeisen@Gang-of-Four.Stanford.EDU (for now)

-----------------------------------------------------------------------------
From: I.Sparry@uk.ac.bath.gdt

Sorry, your question is not quite clear to me. Do you want to
be able to generate the file, or to use it?

To generate it, you can do


find * -print > /tmp/dir_list
/usr/ucb/ex - <<! /tmp/dir_list
%s/.*/& \L&/
%s/\(.*\) \(.*\)/\2 \1/
w
q
!

To use it, use any of the pattern searchers (e.g. grep) followed by
either 'cut' (if you have the system 5 stuff loaded), or "awk '{print $2}'".

Feel free to explain to me why I am stupid not to understand exactly what
you want to do, or to ask for more information/help.
	Icarus

-----------------------------------------------------------------------------
From: jpolcari@com.prime.cat (Joe Polcari x4489)

Try this:

alias LS 'ls|tee /usr/tmp/$$;echo "----------";cat /usr/tmp/$$|tr A-Z a-z'

Then type LS

-joe

-----------------------------------------------------------------------------
From: Jennifer "H." Zemsky <jhz@edu.columbia.cc.cunixa>

>I have a need to be able to get a list of a directory tree and a
>lowercase version of it; this is so that the directory can be
>selected in a case insensitive manner, i.e., they can specify
>contents/info and get information on contents/INFO.
>
this may not be possible, imho.

many unix systems are case-sensitive; thus, given any subdir name with N
letters, you can have 2^N subdirs:
~/abc  ~/ABc
~/Abc  ~/aBC
~/aBc  ~/aBC
~/abC  ~/ABC

of course, my knowledge has limitations.  but, i think you will not be
able to do this without a major test to check any combination
of upper- and lower-case letters.

>
>Thanks in advance

personally, i think AtDhVaAnNkCsE looks better. :^)

--jhz




-----------------------------------------------------------------------------
From: andy@com.icom.xwkg (Andrew H. Marrinson)

Donald,

If you haven't been inundated with responses already, your problem
caught my fancy.  Here is a short shell script to do what you want.
One warning: I don't run SunOS.  Either your tr or your pr might be
different, so beware.

------------ BEGIN SHELL SCRIPT -------------------
#! /bin/sh

cat > /tmp/map$$
tr '[A-Z]' '[a-z]' < /tmp/map$$ | pr -m -s'	' -t /tmp/map$$ -
rm -f /tmp/map$$

------------ END SHELL SCRIPT ---------------------

I wish I could find a way to avoid the temporary file, but Unix pipes
aren't that flexible!  Also, the quotes after pr's -s surroud a single
tab.  It may not make it through all the mailers in the world.  (You
may want to use a different separator -- just change this character.)

Hope this helps...
-- 
		Andrew H. Marrinson
		Icom Systems, Inc.
		Wheeling, IL, USA
		(andy@icom.icom.com)

-----------------------------------------------------------------------------
From: allbery@org.NCoast (Brandon S. Allbery KB8JRR/AA)

In your article <4806@gumby.Altos.COM> ["Mapping of Directory names to lower case"], you wrote:
+---------------
| lowercase version of it; this is so that the directory can be
+-^ that was the first line of your message.  the line-eater lives!  :-)

+---------------
| contents             contents
| contents/data        contents/Data
| contents/info        contents/INFO
| contents/users       contents/users
| contents/users/big   contents/users/BIG
| contents/users/small contents/users/SMALL
+---------------

cd /your/database
find . -print |
sed -e 's!^\./!!' \
    -e h \
    -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmopqrstuvwxyz/ \
    -e 's/$/ /' \
    -e G > DIRECTORY

Amaze your friends with the power of ordinary UNIX commands!  :-)

++Brandon
-- 
Me: Brandon S. Allbery			  Ham: KB8JRR/AA on 2m, 220, 440, 1200
Internet: allbery@NCoast.ORG		(QRT on HF until local problems fixed)
America OnLine: KB8JRR // Delphi: ALLBERY   AMPR: kb8jrr.AmPR.ORG [44.70.4.88]
uunet!usenet.ins.cwru.edu!ncoast!allbery          KB8JRR @ WA8BXN.OH

-----------------------------------------------------------------------------
From: Alan Thew <qq11@uk.ac.liverpool.uxb>

grep has a -i option which ignores case.

-----------------------------------------------------------------------------
From: "Ehud Reshef  edr@techunix.technion.ac.il" <edr@IL.AC.TECHNION.CARMEL>

why not use tr ?
just have your file use all lowercase, and do:
directory=`echo $* | tr '[A-Z]' '[a-z]'`
 
- --
===============================================================================
=
    _                     | Ehud Reshef                    | No good deed
   /_   /_       _ /      | EDR @ Techunix .Bitnet         |    goes
  (___ /  ) (_( (_/       | EDR @ Techunix .Technion.Ac.IL |  unpunished.
 
 
 

-----------------------------------------------------------------------------
From: Perry Statham <perry%statham@edu.utexas.cs>


As I see it you can do it several ways.

If you have a file like:
contents        contents
contents/data   contents/Data
contents/info   contents/INFO

you could do it by writing a shell bourne function like this:

xcd() {
     cd `grep -y "^$1" /tmp/dirfile | awk '{ print $2 }'`
}

or you could simply ignore case by using a program/script to change

    $ xcd contents/info

to perform

    $ cd [cC][oO][nN][tT][eE][nN][tT][sS][/][iI][nN][fF][oO]

Here is a short C program that will change it's first parameter into the
correct format:

/*
* This program prints out its string argument as a 
* regular expression that ignores case.
*/


#include "stdio.h"
#include "ctype.h"

main(argc,argv)
int argc; char *argv[];
{
    int pntr;
    
    for(pntr=0; argv[1][pntr]; pntr++) {
        if (isalpha(argv[1][pntr])) {
            putc('[',stdout);
            putc(toupper(argv[1][pntr]),stdout);
            putc(tolower(argv[1][pntr]),stdout);
            putc(']',stdout);
        } else {
            putc(argv[1][pntr],stdout);
        }
    }
    
    putc('\n',stdout);
}


With this program you would not have to worry about keeping your data
file updated.


Perry Lee Statham        \ /        perry@statham.cactus.org
                        - * -           h> (512) 335-3881
Can You Grok It?         / \            w> (512) 467-1396

-----------------------------------------------------------------------------
From: Jean-Marc_de_chez_Hackers_alias_ <edgard@fr.gipsi.cao>


Hi Donald,

Here is a sh/ksh program wich can, i think, do what you need:
			
------------------------- cut here -------------------------
#@(#) Just for fun, try it :-)  Jean_Marc (edgard@cao.gipsi.fr) [91/04]

read INPUT
DIR=`dirname $INPUT`
case $1 in	-A) OUT=`basename $INPUT | tr '[a-z]' '[A-Z]'`;;
		 *) FILE=`basename $INPUT`
		    OUT=`echo $FILE | cut -c1 | tr '[a-z]' '[A-Z]'`
		    OUT=$OUT`echo $FILE | cut -c2-`
esac
echo "$DIR/$OUT"
------------------------- cut here -------------------------

With "/toto/tutu/titi" in stdin,

*	if you run it without argument, you get:
		/toto/tutu/titi

*	if you run it with '-A' argument, you get:
		/toto/tutu/TITI

Hope that helps,

/*       edgard@cao.gipsi.fr           Voice: (33) (1) 30 60 75 47 */
/* <- In stereo where available ->     Fax:   (33) (1) 30 60 75 90 */

-----------------------------------------------------------------------------
From: Braham Levy <pha21@uk.ac.keele.seq1>

Donald,
	here's a method that might suit your needs. it consists of an
awkscrpit and a shell script. an awkscript follows :-

<=====Cut It Here=====>
BEGIN { FS = "/" }
{ printf "%s ", "lastupper" }
{ if ( NF > 1 ) {
	for (i = 1; i < NF; i++) { printf "%s/", $i }
	print " " $NF;
	}
else { print $NF }
}
END {}
<====End it Here===>

what it does ... splits each line into tokens by setting the field
separator (FS). echoes these tokens out concatting a slash unless its
the last token in which case it echoes it prepending a space.

and a shell script

<====Cut It Here====>
#!/bin/sh
# lastupper concatenates two strings making last on UPPER case
#
# j braham levy april 1991 (all wrongs reserved)
#
echo -n $1
echo $2 | tr a-z A-Z
<===End it Here=====>

what it does... take two arguments, concatting the UPPER case of the 2nd
to the first.

i did it this way 'cause i couldn't figure out how to do a lower to
upper conversion in awk !!

call the awkscript awkscript (for want of anything better) and the shell
script lastupper and then 

	awk -f awkscript < filelist | sh

will do the job... an example for you

consider the input file 

<====Cut It Here====>
contents        
contents/data
contents/info  
contents/users
contents/users/big 
contents/users/small
<====End it Here====>

will produce the following output (well it did on the sequent)


<===Cut It Here====>
contents
contents/DATA
contents/INFO
contents/USERS
contents/users/BIG
contents/users/SMALL
<===End it Here===>

Voila !

i know its crude but as they say "Don't knock it, it's free" (apologies
to D.Adams).

happy hacking

braham

email: brahamlevy@uk.ac.keele (or similar)

mail-mail :				phone +44-782-621111x3943
j braham levy
UDSP Lab,
Electrical Engineering Group,
Dept. of Physics,
University of Keele,
Keele, Staffs, 
UK.



-----------------------------------------------------------------------------
From: pfinkel@com.att.oac (Paul D Finkel)

LIke this?

	echo "Enter directory name: \c"
	read answer
	newdir=`grep $answer file_with_dirnames|cut -f2 -d"	"`
	ls -l $newdir # Other operations can be performed on $newdir

	#This will prompt use for dir name.
	# Grep will find the line with that name. The cut command
	# will cut the desired field (provided the fields are seperated by
	# a tab)

	# Variable substitution will jam the new dir name into "answer"
-- 
  Family motto: Semper ubi, sub ubi. mail: attmail!pfinkel  
  "My name is Fink, whaddaya think, I press pants for nothing?"
   (Punch line to corny joke that my father always told!)