4

How would you go about using a single command to empty multiple text files in terminal?

My thought was that you could use something along these lines...:

find /var/log/apache2/*log -exec `echo > '{}'` \;

I know it's simple enough to create a shell script that would easily do that:

echo "#!/bin/sh\n\necho \"\" > \"$1\"" > /usr/local/bin/empty && chmod +x /usr/local/bin/empty

...

find /var/log/apache2/*.log -exec empty {} \;

But is it possible to do this without creating your own script in a similar manner?

Highway of Life
  • 22,803
  • 16
  • 52
  • 80

4 Answers4

10
#!/bin/bash

for file in /var/log/apache2/*.log; do
  : > "$file"
done

Or the one-liner version

for file in /var/log/apache2/*.log; do : > "$file"; done

If you need to recurse into subdirs, then you can use the following two options:

Bash 4.X

shopt -s globstar; for file in /var/log/apache2/**.log; do : > "$file"; done

Posix

find /var/log/apache2 -type f -name "*.log" -exec sh -c 'for f; do : > "$f"; done' _ {} +
SiegeX
  • 135,741
  • 24
  • 144
  • 154
4

You can also use : >(tee *.log) to spawn the tee(1) program to perform the truncation:

$ ls -l
total 1284
-rw-r--r-- 1 sarnold sarnold  10161 2011-12-30 17:47 alternatives.log
-rw-r----- 1 sarnold sarnold  50976 2011-12-30 17:47 auth.log
-rw-r--r-- 1 sarnold sarnold    759 2011-12-30 17:47 boot.log
-rw-r--r-- 1 sarnold sarnold  41377 2011-12-30 17:47 bootstrap.log
-rw-r----- 1 sarnold sarnold      0 2011-12-30 17:47 daemon.log
-rw-r--r-- 1 sarnold sarnold  73075 2011-12-30 17:47 dpkg.log
-rw-r--r-- 1 sarnold sarnold   2914 2011-12-30 17:47 fontconfig.log
-rw-r----- 1 sarnold sarnold 152295 2011-12-30 17:47 kern.log
-rw-r----- 1 sarnold sarnold      0 2011-12-30 17:47 lpr.log
-rw-r----- 1 sarnold sarnold    950 2011-12-30 17:47 mail.log
-rw-r--r-- 1 sarnold sarnold 212115 2011-12-30 17:47 pm-powersave.log
-rw-r--r-- 1 sarnold sarnold 413195 2011-12-30 17:47 pm-suspend.log
-rw-r--r-- 1 sarnold sarnold      0 2011-12-30 17:47 pycentral.log
-rw-r----- 1 sarnold sarnold      0 2011-12-30 17:47 ufw.log
-rw-r----- 1 sarnold sarnold      0 2011-12-30 17:47 user.log
-rw-r--r-- 1 sarnold sarnold 210426 2011-12-30 17:47 Xorg.0.log
-rw-r--r-- 1 sarnold sarnold  93985 2011-12-30 17:47 Xorg.1.log
$ : >(tee *.log)
$ ls -l
total 0
-rw-r--r-- 1 sarnold sarnold 0 2011-12-30 17:47 alternatives.log
-rw-r----- 1 sarnold sarnold 0 2011-12-30 17:47 auth.log
-rw-r--r-- 1 sarnold sarnold 0 2011-12-30 17:47 boot.log
-rw-r--r-- 1 sarnold sarnold 0 2011-12-30 17:47 bootstrap.log
-rw-r----- 1 sarnold sarnold 0 2011-12-30 17:47 daemon.log
-rw-r--r-- 1 sarnold sarnold 0 2011-12-30 17:47 dpkg.log
-rw-r--r-- 1 sarnold sarnold 0 2011-12-30 17:47 fontconfig.log
-rw-r----- 1 sarnold sarnold 0 2011-12-30 17:47 kern.log
-rw-r----- 1 sarnold sarnold 0 2011-12-30 17:47 lpr.log
-rw-r----- 1 sarnold sarnold 0 2011-12-30 17:47 mail.log
-rw-r--r-- 1 sarnold sarnold 0 2011-12-30 17:47 pm-powersave.log
-rw-r--r-- 1 sarnold sarnold 0 2011-12-30 17:47 pm-suspend.log
-rw-r--r-- 1 sarnold sarnold 0 2011-12-30 17:47 pycentral.log
-rw-r----- 1 sarnold sarnold 0 2011-12-30 17:47 ufw.log
-rw-r----- 1 sarnold sarnold 0 2011-12-30 17:47 user.log
-rw-r--r-- 1 sarnold sarnold 0 2011-12-30 17:47 Xorg.0.log
-rw-r--r-- 1 sarnold sarnold 0 2011-12-30 17:47 Xorg.1.log
$ 
sarnold
  • 102,305
  • 22
  • 181
  • 238
  • I like this method over the first one with a for-loop. I'll give +1 if you make it more specific to the question by creating .log files and using `: >(tee *.log)` so he doesn't have to name each file. Although you'll still need to use find or globstar if you want to recurse more than the current dir – SiegeX Dec 31 '11 at 01:29
  • @SiegeX: Excellent suggestion, it drastically improves my example. Thank you! – sarnold Dec 31 '11 at 01:49
4

Or use sed:

sed Q -i *

replacing file contents in place by emptiness.

update with explanation

sed can do all kinds of replacements, e.g. using regular expressions:

$ cat /etc/passwd | sed -e s/^[^:]*/USER/

with the pattern saying "substitute anything until : with USER", giving:

USER:x:0:0:root:/root:/bin/bash
USER:x:1:1:daemon:/usr/sbin:/bin/sh
USER:x:2:2:bin:/bin:/bin/sh
etc etc

Adding -i in the mix, sed can edit files in-place, so you probably NEVER want to do this:

$ sed -e s/^[^:]*/USER/ -i /etc/passwd

(Note that on e.g. Mac OS X, you need to put in an extra argument after -i to provide the "backup suffix", which is used to make backups before sed does its magic on your files)

Now the quest is for the shortest sed script to lose all input, which is either d or Q. d would delete all input (and then output nothing), Q would quit immediately (and output nothing). Q is presumably fastest.

Then, the sarnold example would look like:

$ ls -l
-rw-r--r-- 1 sarnold sarnold  10161 2011-12-30 17:47 alternatives.log
-rw-r----- 1 sarnold sarnold  50976 2011-12-30 17:47 auth.log
-rw-r--r-- 1 sarnold sarnold    759 2011-12-30 17:47 boot.log
$ sed Q -i *.log
$ ls -l
-rw-r--r-- 1 sarnold sarnold 0 2011-12-30 17:47 alternatives.log
-rw-r----- 1 sarnold sarnold 0 2011-12-30 17:47 auth.log
-rw-r--r-- 1 sarnold sarnold 0 2011-12-30 17:47 boot.log
$ 
mvds
  • 45,755
  • 8
  • 102
  • 111
  • Hi, thanks for your answer. However, it is very vague. +1 if you can provide a working example and explanation. :) – Highway of Life Dec 31 '11 at 01:45
  • 1
    This is superbly clever; the `d` is the entire `sed(1)` script, which says "delete". The `-i` asks `sed(1)` to perform the editing "in place", without making back up files. `sed d -i *.log` is the better fit for your question. – sarnold Dec 31 '11 at 01:50
  • Totally agree. mvds, if you can edit your answer to reflect the description and example @sarnold provided, I'll choose your answer. Thanks! – Highway of Life Dec 31 '11 at 02:27
  • Done, but I must say I would not use this in practice. It's funny (like the `tee` method) but one year from now you, or anyone else will completely miss what's going on. – mvds Dec 31 '11 at 03:13
0

Invoke the shell executable in -exec.

Community
  • 1
  • 1
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358