1

I'm trying to make a tar.tgz file using command substitution

There are backups of 17 Aug 2012

-rw-r----- 1 ossec  502 804M Aug 17  2012 BKPMDISINT_i6nir20j.F_bkp
-rw-r----- 1 ossec  502 2.7G Aug 17  2012 BKPSYFINT_i5nir20j.F_bkp
-rw-r----- 1 ossec  502 3.9G Aug 17  2012 BKPMSFFINT_i4nir20j.F_bkp
-rw-r----- 1 ossec  502  28M Aug 17  2012 c-651746692-20120817-00
-rw-r----- 1 ossec  502 2.0G Aug 17  2012 ALG_KLPFINT_ianir576.alg
-rw-r----- 1 ossec  502 1.5G Aug 17  2012 ALG_KLPFINT_i8nir576.alg
-rw-r----- 1 ossec  502  37M Aug 17  2012 ALG_KLPINT_ibnir64h.alg
-rw-r----- 1 ossec  502 2.2G Aug 17  2012 ALG_KLPFINT_i9nir576.alg
-rw-r----- 1 ossec  502  28M Aug 17  2012 c-651746692-20120817-01
-rw-r----- 1 ossec  502  27M Aug 17  2012 ctrl_170803

So i need to tar them. I used this command

tar -zcvf DB-Backup-17082012.tgz $(ls -lrth|grep "Aug 17")

But it gave me this error

tar: You may not specify more than one `-Acdtrux' option
Try `tar --help' or `tar --usage' for more information.
2
  • 2
    You do realize that the ls -l | grep "Aug 17" will also match files modified on Aug 17 within the past six months, as well as any file which happens to have "Aug 17" in its name, right? Generally, never parse the output of ls. I suggest looking at using find, and paying particular attention to -daystart and -mtime.
    – user
    Jun 26, 2013 at 14:24
  • Also that command won't work because your sending the entire line of output from ls -l to tar. You need to cut it up with either the cut command or awk.
    – slm
    Jun 26, 2013 at 14:58

4 Answers 4

6

If you do $(ls -lrth|grep "Aug 17") you get the whole line, not just the filenames as argument to tar, so that will not work. In general you should not parse the output of ls.

What you can do if you have relatively recent version of Gnu find ( >= v4.3.3 ) is

find . -maxdepth 1 -newermt 20120817T0000 -not -newermt 20130818T0000 -print0 \
    | cpio --create --null  --format=ustar \
    | gzip > DB-Backup-17082012.tgz

If your find does not support -newermt you can create two files with touch with those date-timestamps and just use -newer. Of course you can also use -daystart -mtime but you would need to calculate the number of days (or use trial and error).

One recommendation I have is to use dates in files in the form YYYYMMDD. First of the sort nicer if you have multiple files that start with the same string up to the date and second something like 05062012 would be ambiguous depending on the person looking at the file name ( June 5th (Europe) or May 6th (USA)). So although 1708 has to be August 17th, I would call the file DB-Backup-20120817.tgz

0
2

Your way

You can surely do what you want but it is probably dangerous given some files might have spaces in their names. Here's one way to do it though.

$ tar -zcvf DB-Backup-17082012.tgz $(ls -lrth|grep "Aug 17"|awk '{print $9}')

This will get rid of all the other column data that you're getting from the ls -lrth and just give you the file names.

Using find & tar: method #1

You can use the Unix find command to get a list of all the files that were last modified on a given date and pipe this list to tar as follows:

$ find . -type f -newermt 2012-08-17 ! -newermt 2012-08-18 -print0 | \
   xargs -0 tar zcvf DB-Backup-17082012.tgz

The above will only find files that were last modified on 2012-08-17 but nothing newer. The -print0 tells find to split the files that it outputs using null characters (\0) and the xargs -0 takes each of these files and builds up invocations of tar adding the files in batches at a time.

This is probably the least performant way to do this.

NOTE: This method also runs the risk of losing files if your have more than can be passed as command line arguments to the tar command.

Using find & tar: method #2

The -print0 and the xargs -0 are redundant and you can use just find to generate the list and call tar directly:

$ find . -type f -newermt 2012-08-17 ! -newermt 2012-08-18 \
   -exec tar zcvf DB-Backup-17082012.tgz {} \+

The {} \+ arguments to find above will do 2 things. The {} will substitute the name of each file as find finds it in this position when calling tar and the \+ tells find to keep putting as many files as it can on the command line before calling tar. This saves you on having to invoke tar 100 times if you have 100 files to add to it.

References

9
  • I hope you realise that if you "xargs tar" and the commandline becomes too long tar will be started multiple times and only the last version is maintained. The number of chars is large (100K or so), but I have seen xargs invoke its commands multiple times in real life.
    – Anthon
    Jun 26, 2013 at 21:12
  • @Anthon - Thanks I'll add the clarification.
    – slm
    Jun 26, 2013 at 21:20
  • 1
    @Anthon These days the default limit on Linux is 2MB (it was 128kB for a long time). This reduces the risk in practice, but doesn't eliminate it. Jun 26, 2013 at 23:36
  • @Gilles - do you happen to know if the \+ option would suffer from the same issue then?
    – slm
    Jun 26, 2013 at 23:41
  • 1
    Besides the weird quoting in grep "Aug 17"|awk '{print $9'}, note also that this is equivalent to awk '/Aug 17/{print $9}'. See also partmaps.org/era/unix/award.html#grep
    – tripleee
    Jun 27, 2013 at 5:28
0

Your current format ls|grep "Aug 17" does not output anything. Instead, use the following format:

$ ls -ltr  | grep 'Aug 17'
1
  • Oh sorry it was ls -lrth , I copied the wrong command. Question updated
    – OmiPenguin
    Jun 26, 2013 at 14:19
-1

regarding the $(ls -lrth|grep "Aug 17") this awk line would probably extract the dates you want:

$(ls -lrth|awk '/Aug/&&/17{print $0}')
4
  • You should point out that this only works for the limited list of filenames provided. In general the output of ls cannot be processed (filenames might contain spaces and/or newlines etc.)
    – Anthon
    Jun 26, 2013 at 18:22
  • ah your right, though in this particular case it works (which has me questioning the downvote...) Jun 26, 2013 at 20:35
  • If you answer something on SX you should IMHO take care to point where the limitations are. Someone else might come up with a similar situation but not so well behaved files and would not understand why it does work for him/her. (It was not me who downvoted, so someone else must think your answer is not so useful).
    – Anthon
    Jun 26, 2013 at 21:05
  • I apologize, I should've added I didn't think it was you who downvoted me since your comment didn't seem completely negative. Either way I'm a complete beginner when it comes to this stuff so any feedback is welcome Jun 26, 2013 at 21:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .