
Есть два каталога с множеством файлов. Эти файлы всегда совпадают по именам и не всегда совпадают по размеру. Например:
/dir1
|-file1 (1 MB)
|-file2 (2 MB)
|-file3 (3 MB)
/dir2
|-file1 (1 KB)
|-file2 (2 MB)
|-file3 (10 MB)
Как видите, имена файлов совпадают, но размер файла совпадает только в file2. Как мне сравнить файлы в этих 2 каталогах и выбрать только те, которые больше? Вывод в примере должен быть "/dir2/file3".
Если в dir1 есть файл, который больше, чем файл с тем же именем в dir2 = то ничего не делать. Меня интересуют только файлы в dir2, которые больше, чем файлы в dir1
Я написал скрипт, но он работает только в том случае, если в dir2 найден один файл большего размера.
#!/bin/bash
diff -q $1 $2 | awk '{ print $2,$4 }' > tempfile.txt
A=`cat tempfile.txt | cut -d ' ' -f 1`
B=`ls -s $A | cut -d ' ' -f 1`
C=`cat tempfile.txt | cut -d ' ' -f 2`
D=`ls -s $C | cut -d ' ' -f 1`
if [ "$D" -gt "$B" ]; then
echo $C
fi
решение1
#!/usr/bin/env zsh
zmodload -F zsh/stat b:zstat
for file2 in dir2/*(.); do
file1="dir1/${file2##*/}"
if [ -f "$file1" ] &&
[ "$( zstat +size "$file2" )" -gt "$( zstat +size "$file1" )" ]
then
printf '%s is bigger than %s\n' "$file2" "$file1"
fi
done
Это zsh
скрипт оболочки, который использует встроенную команду zstat
для переносимого получения размеров файлов.
Скрипт будет перебирать все обычные файлы с не скрытыми именами в каталоге dir2
. Для каждого файла в dir2
он будет создавать соответствующий путь для файла в dir1
. Если файл в dir1
существует и является обычным файлом (или символической ссылкой на обычный файл), сравниваются размеры двух файлов. Если файл в dir2
строго больше, выводится короткое сообщение.
Шаблон dir2/*(.)
будет соответствовать только не скрытым именам обычных файлов в каталоге dir2
. (.)
Это zsh
-специфичный модификатор для *
, который заставляет его соответствовать только обычным файлам.
Выражение "dir1/${file2##*/}"
расширится до имени пути, начинающегося с dir1/
и затем содержащего значение $file2
со всем, что было до и включая последнее, /
удалено. Это можно изменить на "dir1/$( basename "$file2" )"
.
решение2
#!/bin/bash
get_attr() {
# pass '%f' to $2 to get file name(s) or '%s' to get file size(s)
find "$1" -maxdepth 1 -type f -printf "$2\n"
}
while read -r file
do
(( $(get_attr "dir2/$file" '%s') > $(get_attr "dir1/$file" '%s') )) \
&& realpath -e "dir2/$file"
done < <(get_attr dir2 '%f')
Это предполагает, что все файлы в dir2
имеют те же имена, что и файлы в dir1
, как вы описали выше.
realpath
печатает абсолютный путь к файлу.
Этот скрипт также сравнивает скрытые файлы (файлы, начинающиеся с .
).