Я пишу сценарий, где я должен сравнить 2 каталога (рекурсивно) и выписать только файлы, если у них есть другой размер, или время изменяют (DD MM YY 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 заказанных списка файлов в данных каталогах и подкаталогах и их размере и в последний раз измененной метке времени.
Теперь я должен так или иначе сравнить их и получить их к указанному формату выше. Я пытался использовать разность-y, но она выдерживает сравнение линию за линией, но мне нужно то же имя к тому же имени. Я также попробовал коммуникацию, но не знайте, как преобразовать тот выходной формат.
Какие-либо идеи?
Я думаю, что попытался бы соединить что-то базирующееся вокруг использования 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
Я думаю, что Вы уже закончили, вот ниже для:
Если файл существует только в directory1 (рассматривающий любые различия в имени, размере или время изменения:
grep -Fxvf dir2.txt dir1.txt > inDir1Only
Или Если файл существует только в directory2:
grep -Fxvf dir1.txt dir2.txt > inDir2Only
Таким образом в конце для Вашего вопроса "выписывают только файлы, если у них есть другой размер, или время изменяют (DD MM YY HH:MM)", просто конкатенируйте два выше результатов, как следующее:)
принятие inDir1Only и inDir2Only содержание как следует:
$ 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