任务
我需要编写一个 bash 脚本,按月归档文件。也就是说,修改日期为 的文件2016-12
将被打包到 archive 中2016-12_archive.tar.gz
,修改日期为 的文件2017-01
将被打包到2017-01_archive.tar.gz
archive 中,等等。
例子:
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
我的困难
我遇到的主要问题:
如何通过bash获取文件修改日期?
如何处理给定目录中的所有文件(以便它们已存档在适当的存档中)?
我尝试解决问题
我找到了两种查找文件修改日期的方法:
date -r $ file +% F
和find dir -name filename -printf '% TY-% Tm-% Td \ n'
。它们都不能在计算机上运行(操作系统 AIX,我不是 root)。另外,我无法获取命令“ls -lc”显示的内容(它似乎没有修改日期)。我只有一个想法:以该
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 文件。
请注意,如果您的文件名包含换行符,这将会中断,但我希望这不会成为日志文件的问题。