仅写出位于一个目录或其他目录中的文件或具有不同大小或最后修改时间的文件

仅写出位于一个目录或其他目录中的文件或具有不同大小或最后修改时间的文件

我正在编写一个脚本,需要比较两个目录(递归),并且仅写出文件(如果它们的大小或修改时间(YY-MM-DD HH:MM)不同或者文件仅存在于一个目录中)。

输出格式为:

<dir1>:<local-path> <size> <last-modify> <dir2>:<local-path> <size> <last-modify>

如果文件仅存在于一个目录中:

<dir1>:<local-path> <size> <last-modify>

或者

<dir2>:<local-path> <size> <last-modify>

到目前为止,我已设法使用以下方法获取指定格式的数据:

find dir1 -type f -exec stat -c '%n %s %y' {} \; | sed 's,^[^/]*/,,' | sed 's/\:[^:]*$//' | sort # > dir1.txt
find dir2 -type f -exec stat -c '%n %s %y' {} \; | sed 's,^[^/]*/,,' | sed 's/\:[^:]*$//' | sort # > dir2.txt

它为我提供了给定目录和子目录中文件的 2 个有序列表以及它们的大小和最后修改时间戳。

现在我需要以某种方式比较它们并将它们转换为上面指定的格式。我尝试使用 diff -y,但它逐行比较,但我需要同名同名。我也尝试了 comm,但不知道如何转换该输出格式。

有任何想法吗?

答案1

rsync我想我会尝试在空运行模式(--dry-run或)下使用一些东西-n

为了说明,给出:

$ tree -Ds Adir/ Bdir/
Adir/
├── [       4096 Nov 19  9:36]  sub1
│   ├── [         35 Nov 19  9:35]  common
│   └── [         23 Nov 19  9:36]  onlyA
├── [       4096 Nov 19  9:41]  sub2
│   ├── [         35 Nov 19  9:35]  common
│   ├── [         44 Nov 19  9:44]  newerA
│   ├── [         44 Nov 19  9:37]  olderA
│   └── [          6 Nov 19 10:36]  size
└── [       4096 Nov 19  9:35]  sub3
    └── [         35 Nov 19  9:35]  common
Bdir/
├── [       4096 Nov 19  9:46]  sub1
│   └── [         35 Nov 19  9:35]  common
├── [       4096 Nov 19 10:36]  sub2
│   ├── [         35 Nov 19  9:35]  common
│   ├── [         44 Nov 19  9:38]  newerA
│   ├── [         44 Nov 19  9:44]  olderA
│   └── [         24 Nov 19 10:36]  size
└── [       4096 Nov 19  9:40]  sub3
    ├── [         35 Nov 19  9:35]  common
    └── [         23 Nov 19  9:40]  onlyB

6 directories, 14 files

然后我们可以列出具有不同大小或修改时间的文件,如下所示:

$ rsync -aOn --delete --itemize-changes Adir/ Bdir/
*deleting   sub3/onlyB
>f+++++++++ sub1/onlyA
>f..t...... sub2/newerA
>f..t...... sub2/olderA
>f.s....... sub2/size

[更改字符串对于我们的目的来说实际上并不重要,但例如*deleting表示sub3/onlyB在源目录中不存在;s表示大小差异;t表示修改时间的差异。]

不幸的是,似乎无法直接从 rsync 输出中获取实际的时间戳,但我们可以简单地读取文件列表并统计每个目录中的相应文件:

#!/bin/bash

dirA="$1"
dirB="$2"

rsync -aOn --itemize-changes --delete "$dirA"/ "$dirB"/ | while read -r c f ; do
  printf '%s:%s  ' "$dirA" "$(cd "$dirA" && stat -c '%n %s %y' "$f" 2>/dev/null || printf '(none) - - - -')"
  printf '%s:%s\n' "$dirB" "$(cd "$dirB" && stat -c '%n %s %y' "$f" 2>/dev/null || printf '(none) - - - -')"
done

我们可以按如下方式使用

$ ./rstat.sh Adir Bdir | column -t
Adir:(none)       -   -           -                   -      Bdir:sub3/onlyB   23  2016-11-19  09:40:12.253318393  -0500
Adir:sub1/onlyA   23  2016-11-19  09:36:52.220421434  -0500  Bdir:(none)       -   -           -                   -
Adir:sub2/newerA  44  2016-11-19  09:44:45.953236221  -0500  Bdir:sub2/newerA  44  2016-11-19  09:38:33.270838033  -0500
Adir:sub2/olderA  44  2016-11-19  09:37:41.675642039  -0500  Bdir:sub2/olderA  44  2016-11-19  09:44:45.953236221  -0500
Adir:sub2/size    6   2016-11-19  10:36:31.460487036  -0500  Bdir:sub2/size    24  2016-11-19  10:36:31.460487036  -0500

答案2

我想你已经结束了,下面是:

如果文件仅存在于目录 1 中(考虑名称、大小或修改时间的任何差异:

grep -Fxvf dir2.txt dir1.txt > inDir1Only

或者如果文件仅存在于目录 2 中:

grep -Fxvf dir1.txt dir2.txt > inDir2Only

因此,对于您的问题“仅写出大小或修改时间(YY-MM-DD HH:MM)不同的文件”,只需将上述两个结果连接起来,如下所示:)

假设仅限目录1仅限 inDir2内容如下:

$ cat inDir1Only
    c.txt 26 2016-11-04 14:23
    b.txt 26 2016-11-04 14:23
$ cat inDir2Only
    b.txt 57 2016-11-04 18:20
    a.txt 14 2016-11-04 18:11

awk因为执行以下命令后你想要的输出如下所示,

$ awk 'NR==FNR{seen[$1]=$0;next} {
    print "inDir1Only:"$0, ($1 in seen) ?"inDir2Only:"seen[$1]:"";seen[$1]=""}
END{
    for(x in seen) if (seen[x]!=NULL) print "inDir2Only:"seen[x]
}' inDir2Only inDir1Only

inDir1Only:c.txt 26 2016-11-04 14:23 
inDir1Only:b.txt 26 2016-11-04 14:23 inDir2Only:b.txt 57 2016-11-04 18:20
inDir2Only:a.txt 14 2016-11-04 18:11

相关内容