10

I'm writing shell script to backup files older than 7 days. Here is my code. But i'm not getting expected result. Can anyone correct me?

#!/bin/bash
# Backup files

files=($(find /var/log/ -mtime +"7"))
 for files in ${files[*]}
 do
         echo $files
         tar cvfz backup.tar.gz $files
 done
Palanikumar
  • 1,706
  • 5
  • 28
  • 51

3 Answers3

14

This will work:

#!/bin/bash
files=()
while IFS=  read -r -d $'\0'; do
    files+=("$REPLY")
done < <(find /var/log/ -mtime +7 -print0)
tar cvfz backup.tar.gz "${files[@]}"

Note the use of "${files[@]}" as opposed to ${files[*]}. "${files[@]}" will expand to provide tar with one argument per file name and will work even if the file names contain spaces, tabs, or newlines. By contrast, after the shell expands ${files[*]}, it will perform word splitting, potentially mangling your file names.

For a detailed explanation of the loop used to create the files array, see: How can I store find command result as arrays in Bash

All files and directories produced by the command find /var/log/ -mtime +7 will be included in the tar file. To include only files, not directories, see Skynet's answer.

To archive logs from the seven most recent days

Only one character need change:

#!/bin/bash
files=()
while IFS=  read -r -d $'\0'; do
    files+=("$REPLY")
done < <(find /var/log/ -mtime -7 -print0)
tar cvfz backup.tar.gz "${files[@]}"

This works because find interprets numeric arguments as follows:

Numeric arguments can be specified as
+n for greater than n,
-n for less than n,
n for exactly n.

Thus, -mtime +7 means greater than 7 days old while -mtime -7 means less than 7. Note that find will ignore fractional parts. Thus +7 will include 8 days old but not 7.5 days old. See man find for details.

John1024
  • 109,961
  • 14
  • 137
  • 171
  • just now noticed its looping continuously. Iteration is not getting stopped. Am i doing anything wrong here? – Palanikumar Jan 28 '15 at 06:28
  • @Palanikumar My version has no loops and no iterations, just two commands. One defines the file list and the other tars the files. So, please tell me what you are seeing. If you are uncertain what is happening, put `set -x` at the beginning of the script. – John1024 Jan 28 '15 at 06:58
  • If you are still receiving error, try modifying the IFS: # save and change IFS OLDIFS=$IFS IFS=$'\n' # read all file name into an array fileArray=($(find $DIR -type f)) # restore it IFS=$OLDIFS Found the solution on http://www.cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html – sho Nov 29 '15 at 09:26
4

Replace your find command with this and try again,

find /var/log -type f -mtime +7 
Arnab Nandy
  • 6,472
  • 5
  • 44
  • 50
0

A bit late to the party, but in searching for a similar solution, I found this simple line to work nicely:

find /var/log -mtime +7 | xargs tar -zcvf archive.tar.gz

Using xargs allows the output of find to make their way into the archive.

S3DEV
  • 8,768
  • 3
  • 31
  • 42