[Eug-lug] To Horst-Q/colours

Allen Brown allen_brown at agilent.com
Tue Jan 4 15:27:13 PST 2005


larry price wrote:
> 
> Well, it's only useful if you are needing to copy a set of
> symlinks from one directory to another, the real value
> comes in knowing the basic parts and combining them to do
> useful things on the spur of the moment.

I think the objective can be met more easily and clearly:

  (cd /usr/blah; tar -cf - $(find . -type l) ) | (tar -xvf -)

(): creates a subshell. That allows us to change the
  directory that find works in without having find report
  the full path.
$(): creates a subshell and returns its stdout to the command
  line.  So all of the files that "find" finds become parameters
  to tar.
find . -type l: gets a list of the symlinks.
tar -cf -: creats an archive of the symlinks and stuffs it
  to stdout
|: pipes the stdout of the first tar into the () subshell's stdin
tar -xvf -: reads the archive from stdin (the subshell)

Bear in mind that this will copy the symlinks exactly.
If you need to translate the directory they point to,
you will need to use something more similar to what Larry
wrote.

> for instance the incantation I used can be broken down
> into it's components like so
> 
> 1. find searches  a given directory for files that are links and runs
> ls -l on them to get the full file names of both the link and it's
> target,
> 
> 2. it's output is piped to sed, line by line, and for each line a
> regular expression is used to write a line 'ln -s target linkname'
> 
> 3. this is saved in a file named tmp which is then evaluated, and then erased.
> 
> the final effect of all this is to make a copy of every symbolic link
> in one directory in another directory. while writing this post, I
> realized it woul be possible to simplify the regex even further by
> using an invocation of ln that only used the target
> 
> On Tue, 04 Jan 2005 12:07:33 +0000, walter fry <kd7kpa at hotmail.com> wrote:
> > I have pencil on paper copied this command string and thought it wiser to
> > ask whether this might be destructive if I entered this as is...is it ok to
> > use?
> >
> > >From: "T. Joseph CARTER" <knghtbrd at bluecherry.net>
> > >Reply-To: Eugene Unix and Gnu/Linux User Group <euglug at euglug.org>
> > >To: larry price <laprice at gmail.com>,Eugene Unix and Gnu/Linux User Group
> > ><euglug at euglug.org>
> > >Subject: Re: [Eug-lug] To Horst-Q/colours
> > >Date: Mon, 3 Jan 2005 23:20:55 -0800
> > >
> > >On Tue, Jan 04, 2005 at 12:56:22AM -0500, larry price wrote:
> > > > On Mon, 3 Jan 2005 21:17:38 -0800, T. Joseph CARTER
> > > > <knghtbrd at bluecherry.net> wrote:
> > > > > They say Linux is free if your time has no value.  For the time
> > >invested,
> > > > > though, you learn about a set of tools that are largely the same ones
> > >that
> > > > > were developed 35 years ago for getting serious work done, and are
> > >still
> > > > > some of the most effective tools for that purpose.  The UNIX shell
> > > > > environment is at times a scary thing for new users, but once you get
> > >the
> > > > > hang of it and how easily you can do most anything you want with it, I
> > > > > think you'll be hard pressed to imagine anything else as worthwhile,
> > >even
> > > > > if it does seem simpler for the time being.
> > > >
> > > > Keep at it, and you might find yourself doing things like this
> > > >
> > > > find /usr/blah/ -type l -exec ls -l {} \; | sed 's/^.* \([^ ].*\) ->
> > > > \(.*\)/ln -s \2 \/usr\/foo\/\1' > tmp; eval tmp; rm tmp
> > > >
> > > > I actually used something like that earlier today, it made sense in
> > >context.
> > >
> > >You're missing a / there before > tmp, and that's disgusting(!) and
> > >clever.  ;)
> > >

For my taste, tho, I prefer to eliminate all temporary
files.  It is almost always possible.

for oldfile in $(cd /usr/blah/; find . -type l); do
  newfile=$(ls -l ${oldfile} | sed 's%^.* \([^ ].*\) -> \(.*\)%\2%')
  ln -s ${newfile} /usr/foo/${oldfile}
done

Notice that if you wanted to do something funny to the filename,
such as changing all upper case to lower case you could do
that by inserting something like this just before the "ln" line.
  oldfile=$(echo ${oldfile} | tr '[A-Z]' '[a-z]')
  newfile=$(echo ${newfile} | tr '[A-Z]' '[a-z]')
-- 
Allen Brown
  work: Agilent Technologies      non-work: http://www.peak.org/~abrown/
        allen_brown at agilent.com	            abrown at peak.org
  I'm just preparing my impromptu remarks. --- Sir Winston Churchill


More information about the EUGLUG mailing list