0

I run some processes which generate a huge number of output files (log, error, warning etc) at my home directory. To find the output files generated on a specific day, let's say 17 Sept 2021, I tried the following command:

find . -type f -newermt 2021-09-17

which is supposed to find all files which are modified on 17 Sept 2021 as referred here, and it does work. However, the command returns not only the output files, but also some hidden files at my home directory such as .history, .viminfo and .cache.

Now, if I try to delete all the files I found with

find . -type f -newermt 2021-09-17 | xargs rm -f

will the hidden files be disastrously deleted as well? If the answer is yes, how should I change it so that the hidden files will be kept and only the output files will be removed?

Hanz
  • 33
  • 1
    Do the files that you want to delete follow some sort of naming pattern that you could also use as a test in the find command? In short, is there some additional way to tell these files apart from files that you do not want to remove? – Kusalananda Sep 20 '21 at 14:32
  • 1
    Adding -name "[^.]*" to the search filter, at least for GNU find – Philippos Sep 20 '21 at 14:38
  • @Kusalananda Some of the files do follow some naming pattern, and I have removed them without issue. The problem is that the remaining files do not have meaningful naming pattern, for example "o123456" or "e123456". – Hanz Sep 20 '21 at 14:56
  • 2
    Don't use find | xargs in the way that you are suggesting, as xargs will split filenames on whitespace and potentially delete the wrong files. (There are easy solutions to this.) – Chris Davies Sep 20 '21 at 15:10
  • 1
    @Philippos that will match ordinary files in dotted directories, which might be problematic for files in the $HOME/.cache directory mentioned by the OP. Perhaps adding -maxdepth 1 to your suggestion would be beneficial. – Chris Davies Sep 20 '21 at 15:11
  • -name '[^.]*' or its POSIX equivalent -name '[!.]*' would also fail to match non-hidden files whose name is not valid text in the locale. – Stéphane Chazelas Sep 21 '21 at 07:12
  • I managed to move and delete the output files successfully. Thanks for your advices and leads. – Hanz Sep 21 '21 at 09:21

1 Answers1

2

find . -type f -newermt 2021-09-17 prints one per line, the regular (f type) files whose last-modification time is newer than the 2021-09-17T00:00:00.000000000 local time, in the current directory or in any level of subdirectories (but not following symlinks). That includes files last-modified on that day, but also later (including those with modification times in the future).

That output is not post-processable reliably¹. If you wanted to delete those files, you'd use -exec rm -f {} + in find, or -delete supported by a few find implementations, most of those that do support -newermt anyway.

But in any case, yes, it would delete any file it is able to, including configuration files, your documents, pictures, etc including hidden ones or the ones in hidden directories.

If you wanted to exclude hidden files (including those in hidden directories such as ~/.config), and only delete files last-modified on that day (and not later), you'd need:

LC_ALL=C find . -name '.?*' -prune -o \
  -type f -newermt 2021-09-17 ! -newermt 2021-09-18 -exec rm -f {} +

You can't use -delete there as -delete (which implies -depth) is incompatible with -prune.

But even then, I would not run that blindly on your home directory.

If you wanted to only delete the files in the current directory and not in subdirectories, you could make it:

LC_ALL=C find . -maxdepth 1 ! -name '.*' \
  -newermt 2021-09-17 ! -newermt 2021-09-18 -type f -delete

If using the zsh shell, you can also do:

autoload age
rm -f -- *(.e['age 2021-09-17'])

zsh globs do skip hidden files by default contrary to find.

Or recursively (still skipping hidden files and dirs):

rm -f -- **/*(.e['age 2021-09-17'])

¹ as the files are newline delimited and newline is as valid as any a character in a file name. More about that at Why is looping over find's output bad practice?

  • Yes, I only intend to delete output files in the home directory and not in the subdirectories. Just to play safe, I decided to move the files (as referred here) to a temp directory so that I can go through them again before removing them, which leads me to this line: find . -maxdepth 1 ! -name '.*' -newermt 2021-09-17 ! -newermt 2021-09-18 -type f -exec mv -t temp {} + before doing rm -rf temp. Thanks for the help. – Hanz Sep 21 '21 at 09:14