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!)