[comp.unix.shell] How to do <cmd> file | hold file

jlhaferman@l_cae07.icaen.uiowa.edu (Jeffrey Lawrence Haferman) (09/08/90)

I had a shell script that used to perform what I have in the
subject line.  For example,  suppose I want to sort a file
and place the result in the same file without destroying it,
e.g.

   % sort file > tmp
   % mv tmp file

I would like a command 'hold' which would do the above via

   % sort file | hold file

Got a good one liner for this (in c-shell)?


Jeff Haferman                            internet: jlhaferman@icaen.uiowa.edu
Department of Mechanical Engineering
University of Iowa
Iowa City IA  52240

rjw@PacBell.COM (Rod Williams) (09/08/90)

>                          ...suppose I want to sort a file
>and place the result in the same file without destroying it,

Doesn't 'sort' allow you to do this already in one easy step?

	sort -o<file> <samefile>

...or did I misunderstand the question?
-- 
* * * * * * * * * * * * * * * * * * * * *         * * * * * * * * * *
*   Rod Williams                        *         entertain         *
*   Pacific Bell - San Ramon CA         *         a thought         *
* * * * * * * * * * * * * * * *         * * * * * * * * * * * * * * *

jms@tardis.Tymnet.COM (Joe Smith) (09/08/90)

In article <2274@ns-mx.uiowa.edu> jlhaferman@l_cae07.icaen.uiowa.edu (Jeffrey Lawrence Haferman) writes:
>For example, suppose I want to sort a file and place the result in the same
>file without destroying it, e.g.
>   % sort file > tmp; mv tmp file

You can use "sort file -o file" for that particular problem.  (It's in the
man pages.)

In general, you have to find a suitable location to hold the file, then
mv it to the destination.  Buffering the entire file in RAM does not work
for large files.
-- 
Joe Smith (408)922-6220 | SMTP: jms@tardis.tymnet.com or jms@gemini.tymnet.com
BT Tymnet Tech Services | UUCP: ...!{ames,pyramid}!oliveb!tymix!tardis!jms
PO Box 49019, MS-C41    | BIX: smithjoe | 12 PDP-10s still running! "POPJ P,"
San Jose, CA 95161-9019 | humorous dislaimer: "My Amiga speaks for me."

fabrice@sj.ate.slb.com (Fabrice Le Metayer) (09/08/90)

In article <1727@pbhyd.PacBell.COM> rjw@PacBell.COM (Rod Williams) writes:
>>                          ...suppose I want to sort a file
>>and place the result in the same file without destroying it,
>
>Doesn't 'sort' allow you to do this already in one easy step?
>
>	sort -o<file> <samefile>
>
>...or did I misunderstand the question?

I use the following C-shell alias to get the output of a command into
the file it applies to. The command should be of the form "<cmd line> <file>".

	alias apply  \!\* \> /tmp/apply.\$\$ \; cp /tmp/apply.\$\$ \!\$
--
Fabrice
--
Fabrice  Le Metayer              DOMAIN : fabrice@sj.ate.slb.com
Schlumberger Technologies - ATE  UUCP   : {amdahl,decwrl,uunet}!sjsca4!fabrice
San Jose, CA  95110              BELL   : (408) 437-5114

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/09/90)

In article <1215@tardis.Tymnet.COM> jms@tardis.Tymnet.COM (Joe Smith) writes:
> In article <2274@ns-mx.uiowa.edu> jlhaferman@l_cae07.icaen.uiowa.edu (Jeffrey Lawrence Haferman) writes:
    [ how to sort a file and place output back into same file? ]
  [ sort -o file file works ]
> In general, you have to find a suitable location to hold the file, then
> mv it to the destination.

No, you don't.

  % ( rm file; foo > file ) < file

foo's input will point at the old file; its output will go into the new
file. If foo reads all its input early and close()s to indicate this,
the disk space for the original will immediately disappear, provided
that it had only one link. If it had several links then the others will
stay around, entirely unaffected.

(I think cp foo bar should work like ( rm -f bar; cat > bar ) < foo, so
that other links to bar won't be affected; but POSIX 1003.2 apparently
disagrees and has cp foo bar work like cat < foo > bar. Oh, well.)

---Dan

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/09/90)

In article <1990Sep8.054623.3822@sj.ate.slb.com> fabrice@sj.ate.slb.com writes:
> I use the following C-shell alias to get the output of a command into
> the file it applies to. The command should be of the form "<cmd line> <file>".
> 	alias apply  \!\* \> /tmp/apply.\$\$ \; cp /tmp/apply.\$\$ \!\$

Much better is

  % alias transform '(rm \!:1;\!:2* > \!:1) < \!:1'

which is used as, e.g., % transform foo.c grep -v '^/\*###' to strip
comments inserted by error(1). It doesn't demand a temporary file. It
can release the disk space of the original as soon as the command closes
it. And it doesn't pass foo.c as an argument if the command is just a
filter.

---Dan

rickert@mp.cs.niu.edu (Neil Rickert) (09/09/90)

In article <8029:Sep903:04:5390@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>(I think cp foo bar should work like ( rm -f bar; cat > bar ) < foo, so
>that other links to bar won't be affected; but POSIX 1003.2 apparently
>disagrees and has cp foo bar work like cat < foo > bar. Oh, well.)
>
 Please don't ever implement 'cp' in the way you suggest.  Doing so would
change file ownership, group, and permissions, not to mention that it would
fail if the file is in directory for which you do not have write permission.
It also messes up multiple links and symbolic links to the file.

-- 
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
  Neil W. Rickert, Computer Science               <rickert@cs.niu.edu>
  Northern Illinois Univ.
  DeKalb, IL 60115.                                  +1-815-753-6940

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/09/90)

In article <1990Sep9.140057.15833@mp.cs.niu.edu> rickert@mp.cs.niu.edu (Neil Rickert) writes:
> In article <8029:Sep903:04:5390@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> >(I think cp foo bar should work like ( rm -f bar; cat > bar ) < foo, so
> >that other links to bar won't be affected; but POSIX 1003.2 apparently
> >disagrees and has cp foo bar work like cat < foo > bar. Oh, well.)
>  Please don't ever implement 'cp' in the way you suggest.  Doing so would
> change file ownership, group, and permissions, not to mention that it would
> fail if the file is in directory for which you do not have write permission.

Which is obviously the sensible solution. Think about what would happen
if files had version numbers: do you really want cp to trash the last
version of the file? Of course not. They're entirely separate versions
and should be creat()ed separately. The fact that they're stored in the
same filename is an accident of creation. (I stole this argument from
comp.std.unix, where this discussion is going on in more depth.)

> It also messes up multiple links and symbolic links to the file.

No; it preserves the multiple links to the original rather than trashing
them, and it leaves the symbolic links with their proper meaning.

Since you can get the write-over behavior with the shell's >, why do you
need it in cp?

---Dan

gorpong@ping.uucp (Gordon C. Galligher) (09/10/90)

In article <1990Sep8.054623.3822@sj.ate.slb.com> fabrice@sj.ate.slb.com writes:
>In article <1727@pbhyd.PacBell.COM> rjw@PacBell.COM (Rod Williams) writes:
>>>                          ...suppose I want to sort a file
>>>and place the result in the same file without destroying it,
>>
>>Doesn't 'sort' allow you to do this already in one easy step?
>>
>>	sort -o<file> <samefile>
>>
>>...or did I misunderstand the question?
>
>I use the following C-shell alias to get the output of a command into
>the file it applies to. The command should be of the form "<cmd line> <file>".
>
>	alias apply  \!\* \> /tmp/apply.\$\$ \; cp /tmp/apply.\$\$ \!\$

You will probably wish to add the following to your alias: \; rm /tmp/apply.\$\$
Without it, you may end up with quite a lot of files in the /tmp directory,
and depending upon the output of the command, this can begin to add up.

Before anyone writes:  "Just use 'mv'"  there is a very valid reason for using
'cp' as opposed to 'mv':  'cp' preserves the permissions on the file you are
copying to, whereas 'mv' does not (ie:  Mv makes the destination file the
same permissions as the source file, cp preserves the permissions on the
destination file).  If you do not believe me, then experiment on your own by 
setting umask, creating a couple of files and making the permissions different
and then using 'mv' and 'cp' combinations and see what happens.

		-- Gordon.
-- 
Gordon C. Galligher	9127 Potter Rd. #2E	Des. Plaines, Ill.    60016-4881
     telxon!ping%gorpong@uunet.uu.net (not tested)  (Is this even legal??)
     ...!uunet!telxon!ping!gorpong      (tested)    (And it works!)
"It seems to me, Golan, that the advance of civilization is nothing but an
 exercise in the limiting of privacy." - Janov Pelorat -- _Foundation's Edge_

schaefer@ogicse.ogi.edu (Barton E. Schaefer) (09/10/90)

In article <8147:Sep903:14:3990@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
} In article <1990Sep8.054623.3822@sj.ate.slb.com> fabrice@sj.ate.slb.com writes:
} > 	alias apply  \!\* \> /tmp/apply.\$\$ \; cp /tmp/apply.\$\$ \!\$
} 
} Much better is
} 
}   % alias transform '(rm \!:1;\!:2* > \!:1) < \!:1'

Of course, if you WANT to put the file name at the end rather than at
the beginning, you can use (sticking with the original alias name):

    % alias apply '( rm \!:$ ; \!:1- > \!:$ ) < \!:$'

but I agree that listing the file first is clearer.

The one problem I see with this is that there ought to be a way to abort
if the rm doesn't happen.  E.g.,

    % transform foo.c grep -v '^/\*###'
    rm: override protection 444 for foo.c?

Unfortunately, no matter what answer is given to this question, "rm"
exits with status 0.  In this particular case the grep command will
fail (on an "n" response) due to lack of write permission on foo.c,
but there are other cases where a problem might occur if the file isn't
rm'd.

Using "mv" would solve this problem, but requires a decision of where
to move the file.
-- 
Bart Schaefer						schaefer@cse.ogi.edu

peter@ficc.ferranti.com (Peter da Silva) (09/10/90)

In article <12272:Sep916:37:0290@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> No; it preserves the multiple links to the original rather than trashing
> them

Which is what it should do. Let's say the file in question is "/bin/smail"
and the link to it is "/bin/rmail"... do you really want these files to get
out of sync?

We have an editor people use here called "aedit", and it behaves the way
you want "cp" to behave. It's caused more problems than you would believe.
Multiple links to a file should remain under normal operation.. they're
there for a reason.

> Since you can get the write-over behavior with the shell's >, why do you
> need it in cp?

Designing for the common case. You can get the uncommon case by doing
an "rm" first, so why do you need it in cp?
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
peter@ferranti.com

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/10/90)

In article <HKS5I=B@xds1.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes:
> In article <12272:Sep916:37:0290@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> > No; it preserves the multiple links to the original rather than trashing
> > them
> Which is what it should do. Let's say the file in question is "/bin/smail"
> and the link to it is "/bin/rmail"...

It's not my fault you're running an obsolete system without symlinks or
a proper install program.

  [ editor ]

Of course the editor should use write-over, as it's conceptually
modifying the *same* file. cp is putting a *different* file into the
name previously used for the original.

> > Since you can get the write-over behavior with the shell's >, why do you
> > need it in cp?
> Designing for the common case. You can get the uncommon case by doing
> an "rm" first, so why do you need it in cp?

Okay, these arguments cancel themselves out.

---Dan

les@chinet.chi.il.us (Leslie Mikesell) (09/11/90)

In article <15472:Sep1015:27:3190@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:

>Of course the editor should use write-over, as it's conceptually
>modifying the *same* file. cp is putting a *different* file into the
>name previously used for the original.

Ah, but cp should only replace the *contents of the file*.  The other
semantics associated with a file (i.e the contents of the inode) are
associated with the name, which is not being changed.

A program that associates the same name with a different inode or different
inode attributes might be a useful thing, but it shouldn't be called cp
(at least not in something that claims to be unix).

Les Mikesell
  les@chinet.chi.il.us

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/11/90)

In article <1990Sep11.040043.14727@chinet.chi.il.us> les@chinet.chi.il.us (Leslie Mikesell) writes:
> In article <15472:Sep1015:27:3190@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> >Of course the editor should use write-over, as it's conceptually
> >modifying the *same* file. cp is putting a *different* file into the
> >name previously used for the original.
> Ah, but cp should only replace the *contents of the file*.

No. That is not what cp does. cp copies a file with one name into a new
file with a different name. The shell's > is what you use to replace the
contents of a file.

> The other
> semantics associated with a file (i.e the contents of the inode) are
> associated with the name, which is not being changed.

What are you talking about? The filename has absolutely nothing to do
with the contents of the inode; it's just a way of finding the inode.
Have you forgotten about hard links?

> A program that associates the same name with a different inode or different
> inode attributes might be a useful thing, but it shouldn't be called cp
> (at least not in something that claims to be unix).

Huh? ln is the program that associates a name with a different inode. cp
shouldn't be described this way at all; it associates (a copy of) a
file's contents with a new name. If there's already an association
between that new name and a different file, then cp should either fail
or sever the original association. It most certainly should not preserve
the original association when it's talking about an entirely new file.

Let me put it this way: If you had two programs, cp (copy) and rp
(replace), the first with unlink/create and the second with over-write,
which would you end up using almost all the time? The only time the
semantics of rp would be proper would be when you really were replacing
the old version of a file with a new version---but there's a program
called ``install'' that was designed to do this job.

---Dan

les@chinet.chi.il.us (Leslie Mikesell) (09/13/90)

In article <19911:Sep1113:47:2290@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:

>No. That is not what cp does. cp copies a file with one name into a new
>file with a different name.

Not my cp.  Mine recognizes existing files.

>> The other
>> semantics associated with a file (i.e the contents of the inode) are
>> associated with the name, which is not being changed.

>What are you talking about? The filename has absolutely nothing to do
>with the contents of the inode; it's just a way of finding the inode.

Exactly: you find the inode and it's associated information by its
name.  Using an existing name means that you want to refer to the
inode associated with that name.

>Huh? ln is the program that associates a name with a different inode.

No, ln associates a different name with a particular inode that can
also be found with an existing name.

>Let me put it this way: If you had two programs, cp (copy) and rp
>(replace), the first with unlink/create and the second with over-write,
>which would you end up using almost all the time? The only time the
>semantics of rp would be proper would be when you really were replacing
>the old version of a file with a new version---but there's a program
>called ``install'' that was designed to do this job.

I would always use the over-writing version, because if I have a file
of a certain name, then I have already set the ownership, permissions,
and hard links the way they should be for a file of that name.  When
I cp something to that name, I just want to replace the contents.
For a more philosophical approach: I like commands to be as consistant
as possible under all conditions.  If you cp a file to a device or
FIFO, would you like to have the special file unlinked and the name
re-used for something else?

Les Mikesell
  les@chinet.chi.il.us

gt0178a@prism.gatech.EDU (BURNS,JIM) (09/13/90)

in article <19911:Sep1113:47:2290@kramden.acf.nyu.edu>, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) says:
> In article <1990Sep11.040043.14727@chinet.chi.il.us> les@chinet.chi.il.us (Leslie Mikesell) writes:
>> In article <15472:Sep1015:27:3190@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>> >Of course the editor should use write-over, as it's conceptually
>> >modifying the *same* file. cp is putting a *different* file into the
>> >name previously used for the original.
>> Ah, but cp should only replace the *contents of the file*.

> No. That is not what cp does. cp copies a file with one name into a new
> file with a different name. The shell's > is what you use to replace the
> contents of a file.

The following script demonstrates that neither cp or > change the inode of
the original file s (& therefore, both change the *contents* of the file -
this is std behavior on 3 systems):

+ touch s
+ ll -i s usage.new
123941 -rw-r--r--  1 gt0178a         0 Sep 13 01:52 s
123818 -rw-r--r--  1 gt0178a      1280 Sep 11 01:05 usage.new
+ cp usage.new s
+ ll -i s usage.new
123941 -rw-r--r--  1 gt0178a      1280 Sep 13 01:52 s
123818 -rw-r--r--  1 gt0178a      1280 Sep 11 01:05 usage.new
+ cat
+ 1> s 0< /dev/null
+ ll -i s usage.new
123941 -rw-r--r--  1 gt0178a         0 Sep 13 01:52 s
123818 -rw-r--r--  1 gt0178a      1280 Sep 11 01:05 usage.new

> Huh? ln is the program that associates a name with a different inode. cp
> shouldn't be described this way at all; it associates (a copy of) a
> file's contents with a new name. If there's already an association
> between that new name and a different file, then cp should either fail
> or sever the original association. It most certainly should not preserve
> the original association when it's talking about an entirely new file.

What do you call the "original association" of the file if not its inode?
(Given that both replace the contents.)
-- 
BURNS,JIM
Georgia Institute of Technology, Box 30178, Atlanta Georgia, 30332
uucp:	  ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!gt0178a
Internet: gt0178a@prism.gatech.edu

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/13/90)

In article <13611@hydra.gatech.EDU> gt0178a@prism.gatech.EDU (BURNS,JIM) writes:
: in article <19911:Sep1113:47:2290@kramden.acf.nyu.edu>, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) says:
: > In article <1990Sep11.040043.14727@chinet.chi.il.us> les@chinet.chi.il.us (Leslie Mikesell) writes:
: >> In article <15472:Sep1015:27:3190@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
: >> >Of course the editor should use write-over, as it's conceptually
: >> >modifying the *same* file. cp is putting a *different* file into the
: >> >name previously used for the original.
: >> Ah, but cp should only replace the *contents of the file*.
: > No. That is not what cp does. cp copies a file with one name into a new
: > file with a different name. The shell's > is what you use to replace the
: > contents of a file.
: The following script demonstrates that neither cp or > change the inode of
: the original file s (& therefore, both change the *contents* of the file -
: this is std behavior on 3 systems):

We're all aware of that. I'm arguing that the behavior for cp is
unintuitive.

---Dan

gt0178a@prism.gatech.EDU (BURNS) (09/13/90)

in article <13611@hydra.gatech.EDU>, gt0178a@prism.gatech.EDU (BURNS,JIM) says:
[version 1 of script]

And more to Leslie's point, by adding the chmod, its clear that neither cp
or > change the attributes of the destination file:

+ touch s
+ chmod 700 s
+ ll -i s usage.new
123973 -rwx------  1 gt0178a         0 Sep 13 03:23 s*
123822 -rw-r--r--  1 gt0178a      1280 Sep 13 02:32 usage.new
+ cp usage.new s
+ ll -i s usage.new
123973 -rwx------  1 gt0178a      1280 Sep 13 03:23 s*
123822 -rw-r--r--  1 gt0178a      1280 Sep 13 02:32 usage.new
+ cat
+ 1> s 0< /dev/null
+ ll -i s usage.new
123973 -rwx------  1 gt0178a         0 Sep 13 03:23 s*
123822 -rw-r--r--  1 gt0178a      1280 Sep 13 02:32 usage.new
-- 
BURNS,JIM
Georgia Institute of Technology, Box 30178, Atlanta Georgia, 30332
uucp:	  ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!gt0178a
Internet: gt0178a@prism.gatech.edu

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/13/90)

In article <13613@hydra.gatech.EDU> gt0178a@prism.gatech.EDU (BURNS) writes:
> And more to Leslie's point, by adding the chmod, its clear that neither cp
> or > change the attributes of the destination file:

Once again, we're talking about how cp should work. My conception of a
good cp is that it doesn't replace the contents of the destination file;
rather, it copies a given file into a new name, and unlinks that name if
it happens to exist already.

---Dan

jmm@eci386.uucp (John Macdonald) (09/13/90)

In article <19911:Sep1113:47:2290@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
|Let me put it this way: If you had two programs, cp (copy) and rp
|(replace), the first with unlink/create and the second with over-write,
|which would you end up using almost all the time? The only time the
|semantics of rp would be proper would be when you really were replacing
|the old version of a file with a new version---but there's a program
|called ``install'' that was designed to do this job.

I would use replace (spelled cp).  If the file already exists, then I
almost never want to change its ownerships/permissions - they have
already been set correctly, regardless of the ownerships/permissions
of this particular source of replacement data.  There is a program
called "install" on some systems.  There has been a program called cp
that works with the effect that you call replace since the very early
days of Unix.  It might not have had exactly the replace effect in
1973, but probably has ever since.  There have been a number of scripts
written since then...
-- 
Algol 60 was an improvment on most           | John Macdonald
of its successors - C.A.R. Hoare             |   jmm@eci386