
Es gibt zwei Verzeichnisse mit vielen Dateien. Die Namen dieser Dateien stimmen immer überein, aber die Größe stimmt nicht immer überein. Beispiel:
/dir1
|-file1 (1 MB)
|-file2 (2 MB)
|-file3 (3 MB)
/dir2
|-file1 (1 KB)
|-file2 (2 MB)
|-file3 (10 MB)
Wie Sie sehen, stimmen die Dateinamen überein, aber die Dateigröße stimmt nur in Datei2 überein. Wie kann ich Dateien in diesen beiden Verzeichnissen vergleichen und nur die größeren Dateien auswählen? Die Ausgabe im Beispielfall muss „/dir2/file3“ sein.
Wenn es in dir1 eine Datei gibt, die größer ist als die gleichnamige Datei in dir2, dann nichts tun. Mich interessieren nur Dateien in dir2, die größer sind als die in dir1
Ich habe ein Skript geschrieben, aber es funktioniert nur, wenn eine größere Datei in Verzeichnis 2 gefunden wurde.
#!/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
Antwort1
#!/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
Dies ist ein zsh
Shell-Skript, das den integrierten Befehl verwendet, zstat
um die Dateigrößen portabel abzurufen.
Das Skript durchläuft alle regulären Dateien mit nicht versteckten Namen im dir2
Verzeichnis. Für jede Datei in dir2
wird der entsprechende Pfadname für eine Datei in erstellt dir1
. Wenn die Datei in dir1
existiert und eine reguläre Datei ist (oder ein symbolischer Link zu einer regulären Datei), wird die Größe der beiden Dateien verglichen. Wenn die Datei in dir2
tatsächlich größer ist, wird eine kurze Meldung ausgegeben.
Das Muster dir2/*(.)
stimmt nur mit nicht versteckten Namen regulärer Dateien im dir2
Verzeichnis überein. Es (.)
gibt einen zsh
-specific-Modifikator, *
der dafür sorgt, dass nur reguläre Dateien übereinstimmen.
Der Ausdruck "dir1/${file2##*/}"
wird zu einem Pfadnamen erweitert, der mit beginnt dir1/
und dann den Wert von enthält, $file2
wobei alles davor und einschließlich des letzten /
entfernt wird. Dies könnte in geändert werden "dir1/$( basename "$file2" )"
.
Antwort2
#!/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')
Dies setzt voraus, dass alle Dateien in dir2
die gleichen Namen wie die Dateien in haben dir1
, wie Sie oben beschreiben.
realpath
druckt den absoluten Pfad der Datei.
Dieses Skript vergleicht auch versteckte Dateien (Dateien, die mit einem beginnen .
).