월별 파일 보관

월별 파일 보관

매달 파일을 보관하려면 bash 스크립트를 작성해야 합니다. 즉, 수정 날짜가 있는 파일은 2016-12아카이브에 압축되고 2016-12_archive.tar.gz, 수정 날짜가 있는 파일은 아카이브 2017-01에 압축되는 식입니다.2017-01_archive.tar.gz

예:

FILE NAME   MODIFICATION DATE
file1.log       2016-12-30       ----> 2016-12_archive.tar.gz
file2.log       2016-12-31       ----> 2016-12_archive.tar.gz
file3.log       2017-01-01       ----> 2017-01_archive.tar.gz
file4.log       2017-01-02       ----> 2017-01_archive.tar.gz
file5.log       2017-01-15       ----> 2017-01_archive.tar.gz

내 어려움

내가 겪은 주요 문제는 다음과 같습니다.

  1. bash를 통해 파일 수정 날짜를 얻는 방법은 무엇입니까?

  2. 특정 디렉터리의 모든 파일을 어떻게 처리하여 적절한 아카이브에 보관합니까?

나는 문제를 해결하려고 노력한다.

  1. 파일의 수정 날짜를 찾는 두 가지 방법을 찾았 date -r $ file +% F습니다 find dir -name filename -printf '% TY-% Tm-% Td \ n'. 이들 중 어느 것도 컴퓨터에서 실행되지 않습니다(OS AIX, 저는 루트가 아닙니다). 또한 "ls -lc" 명령이 표시하는 내용을 알 수 없습니다(수정 날짜가 없는 것 같습니다).

  2. 내 아이디어는 하나뿐입니다. YYYY-MM수정된 모든 파일 날짜를 해당 형식으로 가져온 다음 고유한 값 목록을 만드는 것입니다. 그런 다음 이 목록의 각 항목에 대해 적절한 수정 날짜가 있는 모든 파일을 찾습니다.

종합적인 시도

istat수정 날짜를 얻는 데 사용됩니다 .

$ istat filename
Inode 86741 on device 10/8 File
Protection: rw-r-----
Owner: 6361(user2) Group: 621(norgroup)
Link count: 1 Length 116 bytes

Last updated: 16 февраля 2017 г., 14:25:11 MSK
Last modified: 16 февраля 2017 г., 14:25:11 MSK
Last accessed: 16 февраля 2017 г., 16:08:46 MSK

각 파일에 대해 마지막으로 수정된 값을 얻는 방법은 다음과 같습니다.

for logFile in *.log; do
   mdfDate=$(istat $logFile | grep "Last modified");
   echo $logFile $mdfDate
done

산출:

file1.log Last modified: 30 декабря 2016 г., 14:25:11 MSK
file2.log Last modified: 31 декабря 2016 г., 14:26:11 MSK
file3.log Last modified: 01 января 2017 г., 14:27:11 MSK
file4.log Last modified: 02 января 2017 г., 14:28:11 MSK
file5.log Last modified: 15 января 2017 г., 14:29:11 MSK

따라서 다음 단계는 Unix 형식으로 날짜를 추출하는 것입니다.

어떤 이유로 cut제대로 작동하지 않습니다 . Awk너무 무겁고 복잡합니다. 아마도 sed?

답변1

GNU에 접근할 수 있다면 훨씬 쉽습니다 date. 실제로 더 복잡한 언어를 사용하는 것이 더 간단합니다. 예를 들어, Perl은 다음과 같습니다.

#!/usr/bin/perl -w
use strict;
use POSIX qw(strftime);

my $targetDir = $ARGV[0] || ".";
my %tarFiles;
open(my $input, '-|', "find \"$targetDir\" -type f -name '*.log'");
while (<$input>) {
    # remove trailing newlines
    chomp;
    ## Get the file name
    my $file = $_;
    # Open it as a file handle for stat()
    open(my $fh, '<', "$file") or die;
    # Get the file's stats
    my @stats = stat($fh);
    close($fh);
    # modification time
    my $mtime = $stats[9];
    # Convert to YYYY-MM and build the tar file name
    my $tarfile = strftime "%Y-%m_archive.tar.gz", localtime($mtime);
    # Add to the list of files for this tar file
    push @{$tarFiles{$tarfile}}, qq("$file");
}

for my $tarFile (keys(%tarFiles)) {
    # Build the command that creates the tar file
    my $tarCom = "tar cvzf $tarFile @{$tarFiles{$tarFile}}";
    print "COMMAND: $tarCom\n";

    # Uncomment this line to run the command
    # system("$tarCom")
}                           

스크립트를 makeTars.pl파일(또는 원하는 위치)에 저장하고 $PATH실행 가능하게 만든 후( chmod +x /path/to/makeTars.pl) 다음과 같이 실행합니다.

makeTars.pl /path/to/target/dir

예를 들어:

$ ls -l
total 0
-rw-r--r-- 1 terdon terdon 0 Dec 30 00:00  file1.log
-rw-r--r-- 1 terdon terdon 0 Dec 31 00:00  file2.log
-rw-r--r-- 1 terdon terdon 0 Jan  1  2016  file3.log
-rw-r--r-- 1 terdon terdon 0 Jan  2  2016  file4.log
-rw-r--r-- 1 terdon terdon 0 Jan  3  2016  file5.log
-rw-r--r-- 1 terdon terdon 0 Jan  3  2016 'file5 with spaces.log'
$ makeTars.pl .
COMMAND: tar cvzf 2017-02_archive.tar.gz "."
COMMAND: tar cvzf 2016-12_archive.tar.gz "./file2.log" "./file1.log"
COMMAND: tar cvzf 2016-01_archive.tar.gz "./file5 with spaces.log" "./file5.log" "./file4.log" "./file3.log"

원하는 작업이 수행될 것이라는 확신이 들면 system("$tarCom")실제로 tar 파일을 생성할 수 있도록 마지막 줄( )의 주석 처리를 제거하십시오.

파일 이름에 개행 문자가 포함되어 있으면 이것이 중단될 수 있지만 로그 파일에는 이것이 문제가 되지 않기를 바랍니다.

관련 정보