Technical Tips

Horizontal Rule Issue Date

Technical Tips Q. How do I rename "*.foo" to "*.bar", or change file names to lowercase?

A. Why doesn't "mv *.foo *.bar" work? Think about how the shell expands wildcards. "*.foo" and "*.bar" are expanded before the mv command ever sees the arguments. Depending on your shell, this can fail in a couple of ways. CSH prints "No match." because it can't match "*.bar". SH executes "mv a.foo b.foo c.foo *.bar", which will only succeed if you happen to have a single directory named "*.bar", which is very unlikely and almost certainly not what you had in mind.

Depending on your shell, you can do it with a loop to "mv" each file individually. You can use the basename command :

C Shell:

              foreach f ( *.foo ) 
                   set base='basename $f .foo' 
                   mv $f $base.bar 
              end 

Bourne Shell:

              for f in *.foo; do 
                   base='basename $f .foo' 
                   mv $f $base.bar 
              done 

Instead of using "basename", you can use simpler loops like:

C Shell:

              foreach f ( *.foo ) 
                   mv $f $f:r.bar 
              end 

Korn Shell:

              for f in *.foo; do 
                   mv $f ${f%foo}bar 
              done 

You can also use something like sed to strip apart the original file name in other ways, but the general looping idea is the same. You can convert file names into "mv" commands with 'sed', and hand the commands off to "sh" for execution. Try

ls -d *.foo | sed -e 's/.*/mv & &/' -e 's/foo$/bar/' | sh 

Q. How do I {set an environment variable, change directory} inside a program or shell script and have that change affect my current shell?

A. In general, you can't, at least not without making special arrangements. When a child process is created, it inherits a copy of its parent's variables (and current directory). The child can change these values all it wants but the changes won't affect the parent shell, since the child is changing a copy of the original data. Some special arrangements are possible. Your child process could write out the changed variables, if the parent was prepared to read the output and interpret it as commands to set its own variables. Also, shells can arrange to run other shell scripts in the context of the current shell, rather than in a child process, so that changes will affect the original shell. For instance, if you have a C shell script named "myscript":

              cd /very/long/path 
              setenv PATH /something:/something-else 

or the equivalent Bourne or Korn shell script

              cd /very/long/path 
              PATH=/something:/something-else;export PATH 

and try to run "myscript" from your shell, your shell will fork and run the shell script in a subprocess. The subprocess is also running the shell; when it sees the "cd" command it changes *its* current directory, and when it sees the "setenv" command it changes *its* environment, but neither has any effect on the current directory of the shell at which you're typing (your login shell, let's say). In order to get your login shell to execute the script (without forking) you have to use the "." command (for the Bourne or Korn shells) or the "source" command (for the C shell). i.e. you type

              myscript          (in Bourne or Korn shells) 
              source myscript   (in C shell) 

[Issue No.2]


[U logo]
Computing Services Centre
City University of Hong Kong
ccnetcom@cityu.edu.hk

[Home Page][CSC Home][NetComp Home][Content Home][Previous Page][Next Home][Subscribe Form]