4

Let's suppose we have 4 files:

a.zip created on 28 feb 2018
b.zip created on 28 feb 2018
c.zip created on 2 mar 2018
d.zip created on 2 mar 2018

I want to search the 28 Feb files and Tar it.

find ./ -type f -ls | grep 'Feb 28' | tar -czf somefile3.tar --null -T -

But it's not working.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255

4 Answers4

11

With GNU or FreeBSD find and GNU or BSD tar:

find . -type f -newermt 2018-02-28 ! -newermt 2018-03-01 -print0 |
  tar -cf file.tar --null -T -

(note that it excludes files last-modified at the exact nano-second 2018-02-28T00:00:00.000000000 (and could include a file at the time the next day) which on filesystems with nano-second granularity would almost never happen unless the files were created with touch -t/touch -d or were themselves extracted from archives that don't store timestamps with sub-second precision)

POSIXly and assuming file names don't contain newline characters (the standard tar archive format also has extra limitations on file names):

touch -d 2018-02-28T00:00:00 .start
touch -d 2018-03-01T00:00:00 .end
find . -type f -newer .start ! -newer .end ! -path ./.start ! -path ./.end |
  pax -x ustar -w > file.tar

If you wanted all the regular files last modified on any Feb 28, not just 2018, with GNU tools:

find . -type f -printf '%Tm-%Td-%p\0' |
  sed -nz 's/^02-28-//p' |
  tar -cf file.tar --null -T -

The output of find -ls is not post-processable automatically reliably, it's only intended for human consumption.

  • The problem in this case is that you either skip a second or get two days if you are on a leap year. – schily Jul 23 '18 at 11:58
  • @schily, yes for leap years you'd need ! -newermt 2016-02-29. On Linux native file systems (as tagged by the OP), that would be one nano-second missing (and one possibly added) as already noted. With ! -newermt 2018-02-28T23:59:59, that's an entire second missing (1 billion as much), an entire minute with your touch -t approach. The find -printf approach doesn't have the issue. – Stéphane Chazelas Jul 23 '18 at 12:03
  • OpenBSD find does not have -newermt. One would have to touch a separate file and use -newer instead on this system. – Kusalananda Jul 23 '18 at 12:05
  • @Kusalananda Ah OK. IIRC -newermt originated in BSDs, a shame OpenBSD didn't pick it up. – Stéphane Chazelas Jul 23 '18 at 12:06
  • As mentioned already, -newermt looks like a nice enhancement for find and FreeBSD did already added an enhancement to their find that I invented in the 1980s: see -mtime -3y4w and that is in libfind. – schily Jul 23 '18 at 12:10
  • 1
    BTW: there is a problem with 'find | tar' . While it seems that find implementations since a while all support "unlimited" path length, all tar implementations except star don't support that. Star in the most recent version supports "unlimited" path length (8 GB) since a week via star -c -find and this week, there will be a new version that also supports unlimited path length using the vanilla star -c command line. – schily Jul 23 '18 at 13:30
  • Also relevant: https://unix.stackexchange.com/a/321753/135943 – Wildcard Jul 24 '18 at 02:00
  • BTW: I just published a new schilytools tarball that includes the now complete conversion of star for very long path name support. A funny note: GNU tar-1.30 seems to accidently support long path names with gtar -c but it cannot extract the so created archives and gtar -c -T - still does not support long path names. – schily Jul 25 '18 at 10:37
  • @schily, thanks. Does that involve an extension to the tar format? Would other tar implementations be able to extract those archives? – Stéphane Chazelas Jul 25 '18 at 10:42
  • This does not change the tar archive format, since either the POSIX.1-2001 archive format or the pre-POSIX method support path names up to 8 GB. Other tar implementations would need to add complete support for the *at() syscalls and to dynamic path storage in order extract archives with long path names. As mentioned before: gtar-1.30 accidently creates such archives with gtar -c and cannot extract the own archives that have been created this way. – schily Jul 25 '18 at 10:50
4

With star, your command line looks:

touch -t201802280000 ref
star -c -f file.tar -find . -newer ref

BTW: -newermt may be a nice future enhancement for libfind.

If you like an end date as well:

touch -t201802280000 start
touch -t201802282359.59 end
star -c -f file.tar -V pat='start!end' -find . -newer start ! -newer end

Note that you either have to omit one second or you may get two days if the years was a leap year.

Since 2018 isn't a leap year, you may use touch -t201803010000 end.

schily
  • 19,173
3

find has date options. did you try those?

-newermt last modified date

-newerat last accessed date

-newerct last date that permissions changed

for example: find . -newermt 2018-07-10 ! -newermt 2018-7-11 | xargs tar -cfv file.tar EDIT as Charles Duffy comment , to avoid this problem: find . -newermt 2018-07-10 ! -newermt 2018-7-11 -print0 | xargs -0 tar -cfv file.tar

  • 4
    This looks like it was added an hour after another answer concretely showing those options, with more-portable/less-buggy xargs usage? (Note that xargs without -d or -0 arguments behaves badly with filenames with spaces, filenames with literal quote characters, etc). – Charles Duffy Jul 23 '18 at 17:09
3

I just want to add the reason your command is not working

find ./ -type f -ls | grep 'Feb 28' | tar -czf somefile3.tar --null -T -

The output of find is a list of filename together with other information like the date. Grep outputs the full lines with the matching date. Tar expects just the names of the files, and it expects that separated by null-bytes and not newlines.

RalfFriedl
  • 8,981