381 lines
12 KiB
HTML
381 lines
12 KiB
HTML
<!--startcut ======================================================= -->
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
|
<html>
|
|
<head>
|
|
<META NAME="generator" CONTENT="lgazmail v1.3E.n">
|
|
<TITLE>The Answer Gang 62: about Unix command rm</TITLE>
|
|
</HEAD><BODY BGCOLOR="#FFFFFF" TEXT="#000000"
|
|
LINK="#3366FF" VLINK="#A000A0">
|
|
<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
|
|
<P> <hr>
|
|
<CENTER>
|
|
<!-- *** BEGIN navbar *** -->
|
|
<!-- *** END navbar *** -->
|
|
</CENTER>
|
|
</p>
|
|
<P> <hr> <P>
|
|
<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
|
|
<center>
|
|
<H1><A NAME="answer">
|
|
<img src="../../gx/dennis/qbubble.gif" alt="(?)"
|
|
border="0" align="middle">
|
|
<font color="#B03060">The Answer Gang</font>
|
|
<img src="../../gx/dennis/bbubble.gif" alt="(!)"
|
|
border="0" align="middle">
|
|
</A></H1>
|
|
<BR>
|
|
<H4>By Jim Dennis, Ben Okopnik, Dan Wilder, Breen Mullins, Mitchell Bruntel,
|
|
the Editors of Linux Gazette...
|
|
and You!
|
|
<br>Send questions (or interesting answers) to
|
|
<a href="mailto:linux-questions-only@ssc.com">linux-questions-only@ssc.com</a>
|
|
</H4>
|
|
</center>
|
|
|
|
<p><hr><p>
|
|
<!-- endcut ======================================================= -->
|
|
<!-- begin 3 -->
|
|
<H3 align="left"><img src="../../gx/dennis/qbubble.gif"
|
|
height="50" width="60" alt="(?) " border="0"
|
|
>about Unix command rm</H3>
|
|
|
|
|
|
<p><strong>From Jane Liu
|
|
</strong></p>
|
|
<p align="right"><strong>Answered By Mike Orr, Ben Okopnik, Dan Wilder
|
|
<br></strong></p>
|
|
|
|
<!-- sig -->
|
|
|
|
<P><STRONG><IMG SRC="../../gx/dennis/qbub.gif" ALT="(?)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
>
|
|
I have a question about rm command. Would you please tell me how to remove
|
|
all the files excepts certain files like anything ended with .c?
|
|
</STRONG></P>
|
|
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
> [Mike]
|
|
The easiest way (meaning it will work on any Unix systems anywhere), is
|
|
to move those files to a temporary directory, then delete "everything",
|
|
then move those files back.
|
|
</BLOCKQUOTE>
|
|
|
|
<blockquote><code><font color="#000033"><br>mkdir /tmp/tdir
|
|
<br>mv *.c /tmp/tdir
|
|
<br>rm *
|
|
<br>mv /tmp/tdir/* .
|
|
<br>rmdir /tmp/tdir
|
|
</font></code></blockquote>
|
|
|
|
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
> [Ben]
|
|
The above would work, but seems rather clunky, as well as needing a lot of
|
|
typing.
|
|
</blockquote>
|
|
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
> [Mike]
|
|
Yes, it's not something you'd want to do frequently. However, if you don't
|
|
know a lot about Unix commands, and are hesitant to write a shell script
|
|
which deletes a lot of files, it's a good trick to remember.
|
|
</BLOCKQUOTE>
|
|
|
|
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
> [Ben]
|
|
It's true that it is completely portable; the only questionable
|
|
part of my suggestion immediately below might be the "-1" in the "ls", but
|
|
all the versions of "ls" with which I'm familiar support the "single column
|
|
display" function. It would be very easy to adapt.
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
My preference would be to use something like
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE><BLOCKQUOTE><CODE>
|
|
rm $(ls -1|grep -v "\.c$")
|
|
</CODE></BLOCKQUOTE></BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
because the argument given to "grep" can be a regular expression. Given
|
|
that, you can say things like "delete all files except those that end in
|
|
'htm' or 'html'", "delete all except '*.c', '*.h', and '*.asm'", as well as
|
|
a broad range of other things. If you want to eliminate the error messages
|
|
given by the directories (rm can't delete them without other switches), as
|
|
well as making "rm" ask you for confirmation on each file, you could use
|
|
a "fancier" version -
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE><BLOCKQUOTE><CODE>
|
|
rm -i $(ls -AF1|grep -v "/$"|grep -v "\.c$")
|
|
</CODE></BLOCKQUOTE></BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
Note that in the second argument - the only one that should be changed -
|
|
the "\" in front of the ".c" is essential: it makes the "." a literal
|
|
period rather than a single-character match. As an example, lets try the
|
|
above with different options.
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
In a directory that contains
|
|
</BLOCKQUOTE>
|
|
|
|
<blockquote><code><font color="#000033"><br>testc
|
|
<br>test-c
|
|
<br>testcx
|
|
<br>test.cdx
|
|
<br>test.c
|
|
</font></code></blockquote>
|
|
<BLOCKQUOTE>
|
|
".c" means "'c' preceded by any character" - NO files would be deleted.
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
"\.c" means "'c' preceded by a period" - deletes the first 3 files.
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
"\.c$" means "'c' preceded by a period and followed by the end of the line"
|
|
- all the files except the last one would be gone.
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
Here's a script that would do it all in one shot, including showing a list
|
|
of files to be deleted:
|
|
</BLOCKQUOTE>
|
|
<blockquote>See attached
|
|
<a href="../misc/tag/rmx.bash.txt">misc/tag/rmx.bash.txt</a></blockquote>
|
|
|
|
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
> [Dan]
|
|
Which works pretty well up to some limit, at which things
|
|
break down and exit due to $skip being too long.
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
For a less interactive script which can remove inordinate
|
|
numbers of files, something containing:
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE><BLOCKQUOTE><CODE>
|
|
ls -AF1 | grep -v /$ | grep -v $1 | xargs rm
|
|
</CODE></BLOCKQUOTE></BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
allows "xargs" to collect as many files as it can on a command
|
|
line, and invoke "rm" repeatedly.
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
It would be prudent to try the thing out in a directory containing
|
|
only expendable files with names similar to the intended victims/saved.
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
> [Ben]
|
|
Possibly a good idea for some systems. I've just tried it on a directory
|
|
with 1,000 files in it (created just for the purpose) and deleted 990 of
|
|
them in one shot, then recreated them and deleted only 9 of them.
|
|
Everything worked fine, but testing is indeed a prudent thing to do.
|
|
</BLOCKQUOTE>
|
|
|
|
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
> [Dan]
|
|
Or with some typists. I've more than once had to resort to backups
|
|
due to a slip of the fingers (the brain?) with an "rm" expression.
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
> [Ben]
|
|
<*snort*> Never happened to <EM>me</EM>. No sir. Uh-uh.
|
|
<Anxious glance to make sure the weekly backup disk is where it should be>
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
I just put in that "to be deleted" display for, umm, practice. Yeah.
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
<LOL> Good point, Dan.
|
|
</BLOCKQUOTE>
|
|
|
|
<hr width="40%" align="center">
|
|
|
|
<P><STRONG><IMG SRC="../../gx/dennis/qbub.gif" ALT="(?)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
>
|
|
Thanks a million! It worked.
|
|
</STRONG></P>
|
|
<P><STRONG>
|
|
I have another question: My shell script is in a file called hw1d.sh. When I
|
|
run sh hw1d.sh, the output shows on the screen. But the command details
|
|
won't show. Is there a way I can capture the detailed command lines and
|
|
output at the same time?
|
|
</STRONG></P>
|
|
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
> [Ben]
|
|
For one thing, you shouldn't be running your script as "sh ..."; simply
|
|
make it executable via "chmod +x <scriptname>" and run it. Other than
|
|
that (I <EM>think</EM> I understand what you're asking here), you can add "-v"
|
|
to the hashbang line so it looks like this -
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE><BLOCKQUOTE><CODE>
|
|
#!/bin/bash -v
|
|
</CODE></BLOCKQUOTE></BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
This will print out each line as it is read.
|
|
</BLOCKQUOTE>
|
|
|
|
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
> [Mike]
|
|
Or -x, which is what I use. They do slightly different things.
|
|
Consider this program.
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE><BLOCKQUOTE><CODE>
|
|
<BR>#!/bin/bash -v
|
|
<BR>TOWHOM="world"
|
|
<BR>echo "Hello"
|
|
<BR>echo $TOWHOM
|
|
<BR># This is a comment.
|
|
</CODE></BLOCKQUOTE></BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
Now running it:
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE><BLOCKQUOTE><CODE>
|
|
<BR>$ ./hello.sh
|
|
<BR>#!/bin/bash -v
|
|
<BR>TOWHOM="world"
|
|
<BR>echo "Hello"
|
|
<BR>Hello
|
|
<BR>echo $TOWHOM
|
|
<BR>world
|
|
<BR># This is a comment.
|
|
</CODE></BLOCKQUOTE></BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
Now change -v to -x and run it.
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE><BLOCKQUOTE><pre>
|
|
$ ./hello.sh
|
|
+ TOWHOM=world
|
|
+ echo Hello
|
|
Hello
|
|
+ echo world
|
|
world
|
|
</pre></BLOCKQUOTE></BLOCKQUOTE>
|
|
<BLOCKQUOTE>
|
|
The variable was expanded, there's a "+ " before each program line, and
|
|
the comments are omitted. It looks like -v shows the commands <EM>before</EM>
|
|
they're interpreted and -x shows them <EM>after</EM>.
|
|
</BLOCKQUOTE>
|
|
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
> [Ben] For more details on shell scripting, see my
|
|
"Introduction to Shell Scripting" articles in LG53-57 and 59.
|
|
</BLOCKQUOTE>
|
|
|
|
<p><em>He got the issue numbers wrong, but no sense worrying about that,
|
|
here they are. -- Heather</em></p>
|
|
|
|
<ul><li><a href="../../issue52/okopnik2.html">52 - The Basics</a>
|
|
<li><a href="../../issue53/okopnik.html">53 - loops, conditions, good practices</a>
|
|
<li><a href="../../issue54/okopnik.html">54 - handy external tools</a>
|
|
<li><a href="../../issue55/okopnik.html">55 - deep, dark secrets</a>
|
|
<li><a href="../../issue57/okopnik.html">57 - color!</a>
|
|
<li><a href="../../issue58/okopnik.html">58 - cleanup and debugging tricks</a> (last in series)
|
|
</ul>
|
|
|
|
|
|
<P><STRONG><IMG SRC="../../gx/dennis/qbub.gif" ALT="(?)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
>
|
|
Thanks!
|
|
</STRONG></P>
|
|
<P><STRONG>
|
|
For practice purpose, I create file -cfile and try to rename it to cfile. I
|
|
figured out one way:
|
|
</STRONG></P>
|
|
|
|
<pre><strong> >cat <\-cfile >cfile
|
|
</strong></pre>
|
|
<P><STRONG>
|
|
But I just couldn't delete the old file -cfile because shell always
|
|
interprets as option. Is there a way I can do this?
|
|
</STRONG></P>
|
|
|
|
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
> [Dan]
|
|
Yes.
|
|
</blockquote>
|
|
|
|
<pre><blockquote>rm -- -cfile
|
|
</blockquote></pre>
|
|
<blockquote>
|
|
From "man rm":
|
|
</blockquote>
|
|
|
|
<pre><blockquote>GNU STANDARD OPTIONS
|
|
|
|
[ ... ]
|
|
|
|
-- Terminate option list.
|
|
</blockquote></pre>
|
|
|
|
<BLOCKQUOTE><IMG SRC="../../gx/dennis/bbub.gif" ALT="(!)"
|
|
HEIGHT="28" WIDTH="50" BORDER="0"
|
|
> [Ben]
|
|
Given that "there's more than one way to do it",
|
|
</BLOCKQUOTE>
|
|
|
|
<blockquote><pre>rm ./-cfile
|
|
</pre></blockquote>
|
|
<BLOCKQUOTE>
|
|
also works. As you have found out, it's not a good idea to create
|
|
filenames with non-alphanumeric characters at the beginning: just because
|
|
you <EM>can</EM>, really does not mean that you <EM>should</EM>...
|
|
</BLOCKQUOTE>
|
|
|
|
<!-- end 3 -->
|
|
<!--startcut ======================================================= -->
|
|
<P> <hr> </p>
|
|
<!-- *** BEGIN copyright *** -->
|
|
<H5 align="center">This page edited and maintained by the Editors
|
|
of <I>Linux Gazette</I>
|
|
<a href="http://www.linuxgazette.com/copying.html"
|
|
>Copyright ©</a> 2001
|
|
<BR>Published in issue 62 of <I>Linux Gazette</I> February 2001</H5>
|
|
<H6 ALIGN="center">HTML script maintained by
|
|
<A HREF="mailto:star@starshine.org">Heather Stern</a> of
|
|
Starshine Technical Services,
|
|
<A HREF="http://www.starshine.org/">http://www.starshine.org/</A>
|
|
</H6>
|
|
<!-- *** END copyright *** -->
|
|
<P> <hr>
|
|
<!-- begin tagnav ::::::::::::::::::::::::::::::::::::::::::::::::::-->
|
|
<p align="center">
|
|
<table width="100%" border="0"><tr>
|
|
<td align="right" valign="center"
|
|
><IMG ALT="" SRC="../../gx/navbar/left.jpg"
|
|
WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="middle" border="0">
|
|
<A HREF="../lg_answer62.html"
|
|
><IMG SRC="../../gx/dennis/answertoc.jpg" align="middle"
|
|
ALT="[ Answer Guy Current Index ]" border="0"></A></td>
|
|
<td align="center" valign="center"><A HREF="../lg_answer62.html#greeting"><img align="middle"
|
|
src="../../gx/dennis/smily.gif" alt="greetings" border="0"></A>
|
|
<A HREF="1.html">1</A>
|
|
<A HREF="2.html">2</A>
|
|
<A HREF="3.html">3</A>
|
|
<A HREF="4.html">4</A>
|
|
<A HREF="5.html">5</A>
|
|
<A HREF="6.html">6</A>
|
|
<A HREF="7.html">7</A></td>
|
|
<td align="left" valign="center"><A HREF="../../tag/kb.html"
|
|
><IMG SRC="../../gx/dennis/answerpast.jpg" align="middle"
|
|
ALT="[ Index of Past Answers ]" border="0"></A>
|
|
<IMG ALT="" SRC="../../gx/navbar/right.jpg" align="middle"
|
|
WIDTH="14" HEIGHT="45" BORDER="0"></td></tr></table>
|
|
</p>
|
|
<!-- end tagnav ::::::::::::::::::::::::::::::::::::::::::::::::::::-->
|
|
<P> <hr>
|
|
<CENTER>
|
|
<!-- *** BEGIN navbar *** -->
|
|
<!-- *** END navbar *** -->
|
|
</CENTER>
|
|
</p>
|
|
<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
|
|
</BODY></HTML>
|
|
<!--endcut ========================================================= -->
|