cat /dev/null to multiple files to clear existing files like logs
Asked Answered
C

3

9

A good way to clear logs(syslog has a handle on file) which have frozen my linux server(out of space) I tried cat /dev/null > fileABC; cat /dev/null/ > fileXYZ

How can I clear multiple files by cat /dev/null to multiple files in an efficient or single command.

Clevelandclevenger answered 17/6, 2015 at 15:9 Comment(6)
cp dev/null/ whatever does not make sense to me. null is a device fileCoffee
Made some edits.. what I meant was to cat it. pl check this for clearing contents of existing file goo.gl/UJXEy3Clevelandclevenger
@Samuel u r right. but how can I do the same for 10-15 files at a time..Clevelandclevenger
/dev/null is conventionally a destination, not a source. Are you saying you want to overwrite the file with nothing, setting the length to 0?Gothenburg
>fileABC does the same thing, with no cat needed.Georgianngeorgianna
@CharlesDuffy OR printf '' > fileABC as you said in the other commentsClevelandclevenger
S
31

Hard coded solutions

tee

Echo nothing and simply send it to multiple files using the tee command.

Like this:

$ echo -n | tee file1 file2 file3 file4 file5

All files in that list will be empty and created if they don't exist.

Applied to your answer this would be:

$ cat /dev/null | tee fileABC fileXYZ

While echo -n is considered better practice than cat /dev/null, an even better solution would be to use printf '', as noted by Charles Duffy. Resulting in following command:

$ printf '' | tee file1 file2 file3 

truncate

As answered by skrilled, truncate is probably the solution you were originally looking for. The command allows arbitrarily many file name arguments to be supplied. You can easily use it as follows:

$ truncate --size 0 file1 file2 file3 file4 file5

Which allows you to achieve your goal without using any pipe and in a single command, pretty nifty answer supplied here by skrilled.

Structural file names solution

If all files have a structure on their names (for instance files) and location you could use the find command. In the following example I will apply the erasure to all .java and .c source files in the current directory and in all directories inside the current directory.

$ find . -maxdepth 2 -type f -name '*.java' -exec truncate --size 0 "{}" \; 

Explained:

  • find . execute find in current directory .
  • -maxdepth 2 recursion level, descend to directories in directory but no further (level 2). Set this to 1 to not descend or n to descend n times.
  • -type f only apply to files, not directories
  • -name '*.java' only apply to files ending in .java
  • -exec truncate --size 0 "{}" \; truncate each file found (file name is stored in {})

See man find for more options and a more detailed explanation. Be sure to check it out because find is one of the most powerful tools for automation of file editing.

List of files in separate file solution

The easiest thing to do might be to store the files to erase in a file, line by line. If there is no obvious structure with respect to their location and name, that is.

Say the files are stored in a file called erasure.

$ cat erasure
fileABC
fileXYZ
dir/anotherFile

In this example we will erase three files, which are listed above.

$ while read file; do > "$file"; done < erasure

Explanation:

  • while read file for each line in the given file, store the line in variable file
  • do > "$file" empty the file and output nothing in it (i.e. erase it)
  • done < erasure specify the input file using < (redirection)

Note: while this method preserves spaces in the path, it fails to handle backslashes and trailing white space, as noted by Charles Duffy. One way to fix both issues is to modify the loop as follows:

while IFS= read -r file; do > "$file"; done < erasure

Yet newlines in file names will still be a problem. The only way around this issue is to separate the file names using null termination (\0). The correct loop now becomes:

while IFS= read -r -d '' file; do > "$file"; done < erasure
Samella answered 18/6, 2015 at 23:55 Comment(10)
Thanks. cat /dev/null | tee fileABC fileXYZ works but I didnt understand echo command and why are we using that here. Second code snippet suffices right? Am I missing somethingClevelandclevenger
They are equivalent, echo -n is a zero output, which is considered better practice than cat /dev/null. Don't forget to accept if the answer helped and upvote if you deem it a quality answer.Samella
@ShellFish, I'd argue that printf '' is much better practice than echo -n -- see the POSIX echo spec at pubs.opengroup.org/onlinepubs/009604599/utilities/echo.html, and note that while -n is part of BSD echo, it's not there in the SysV-derived spec.Georgianngeorgianna
...as for the while read file approach, this is quite buggy as-given: Doesn't correctly handle filenames with literal backslashes, for instance (would need read -r), doesn't handle filenames whose names end in whitespace (would work with IFS= read); doesn't handle filenames containing literal newlines (which can't be fixed while still using line-oriented rather than NUL-delimited input).Georgianngeorgianna
Thank you for your comments, as always, it's great to learn from an experienced guy like you. I will update my post when I get home and will of course credit you. Thanks for the pointers!Samella
@Samella Great solution and thanks for the insight. Appreciate it.Clevelandclevenger
Wow. Now that's what we call a comprehensive answer. Great stuff.Jimerson
"Structural file names solution" doesn't work with multiple files the -o argument find /root/bc/ -type f -name debug.log -o -name db.log -exec truncate --size 0 "{}" \; only last file db.lg will be truncated, but if you run this without -exec find will display all files. How to solve this?Quality
found an answer here tecmint.com/…Quality
more abbreviated (be careful): cat /dev/null | tee file* instead of cat /dev/null | tee file1 file2 file3Venial
M
5

Truncate can be used to empty a file as well.

truncate --size 0 /path/to/file/here
Mccaleb answered 17/6, 2015 at 19:46 Comment(2)
I dont have truncate installed on my box but sure.. taht will do but can I have multiple files listed next to each other? say: "truncate --size 0 log1 log2 log3?Clevelandclevenger
truncate is indeed the best solution but the main issue is handling several files. While truncate indeed supports multiple files, it should be added to the answer to clear that up for the OP. So I'd just append another file name to the command. Great answer though, if my answer ends up being accepted I will include this in the answer if it's okay with you (of course you'll be credited).Samella
M
0

You can do it quite nicely with GNU Parallel like this:

parallel '>' ::: TooLong.log BigBoy.dat NonExistant.file
Mellifluous answered 22/12, 2017 at 19:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.