Сравните файлы и выберите больший

Сравните файлы и выберите больший

Есть два каталога с множеством файлов. Эти файлы всегда совпадают по именам и не всегда совпадают по размеру. Например:

/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печатает абсолютный путь к файлу.

Этот скрипт также сравнивает скрытые файлы (файлы, начинающиеся с .).

Связанный контент