我正在使用 chroot 为我自己的操作系统构建软件包。我在存档文件中有 chroot,在构建过程开始时,它会下载两次并提取。我需要一个命令,从构建包的 chroot 文件夹中删除文件,这些文件与第二个 chroot 文件夹中的文件相同(例如通过其哈希值)。我尝试了 Unix StackExchange 中的几个命令,但没有一个起作用。
编辑:这必须是全自动的
答案1
和fdupes
:
fdupes -drN dir1 dir2
这将删除两个目录中多次找到的所有内容。任何骗局的第一个发现的副本都会被保留。
有长选项:
fdupes --delete --recurse --noprompt dir1 dir2
请注意,这还会删除与dir1
同一目录中其他文件重复的文件。
在具有 GNU 工具的系统上,dir1
如果您自己编写脚本,则可以通过删除重复项来解决此问题:
#!/bin/sh
dir1=somedir
dir2=someotherdir
sums1=$(mktemp)
sums2=$(mktemp)
# Remove temporary files when done.
trap 'rm -f "$sums1" "$sums2"' EXIT
# Calculate checksums for first directory, extract only the checksums
# themselves and sort them (removing duplicate checksums).
find "$dir1" -type f -exec md5sum -z {} + |
cut -z -c -32 |
sort -z -u -o "$sums1"
# Calculate the checksums for the second directory, and sort them.
find "$dir2" -type f -exec md5sum -z {} + |
sort -z -o "$sums2"
# Join the files on the first column, extract the pathnames for the
# files in the second directory that have the same checksum as files in
# the first directory, and delete these files.
join -z "$sums1" "$sums2" |
cut -z -c 34- |
xargs -0 rm -f
# Optionally, delete empty directories in the second directory
# find "$dir2" -type d -empty -delete
上面的代码还尝试通过将路径名作为 nul 终止列表传递来确保正确处理任何有效的文件名。
bash
上述脚本的较短变体:
#!/bin/bash
dir1=somedir
dir2=someotherdir
join -z \
<(find "$dir1" -type f -exec md5sum -z {} + | cut -z -c -32 | sort -z -u) \
<(find "$dir2" -type f -exec md5sum -z {} + | sort -z) |
cut -z -c 34- |
xargs -0 rm -f
答案2
以下是比较所有文件的哈希值的方法。
方法一(推荐):
谢谢善行难陀建议使用join
它来简化任务。您可以使用以下命令。请注意,如果任何文件的名称中包含空格,则此操作将不起作用。
# DIR1 is the main directory
# DIR2 is from where files will get deleted. Change the values accordingly
DIR1="$PWD"
DIR2="$HOME"
find $DIR1 -type f | xargs md5sum 2>/dev/null | sort > /tmp/m1
find $DIR2 -type f | xargs md5sum 2>/dev/null | sort > /tmp/m2
join /tmp/m1 /tmp/m2 > /tmp/m3
cat /tmp/m3 | cut -d ' ' -f3 | xargs rm -f
# To delete empty directories
find $DIR2 -type d -empty -delete
方法二:
这里我们只是重复计算两个目录中所有文件的哈希值,如果相同则删除该文件。
# DIR1 is the main directory
# DIR2 is from where files will get deleted.
DIR1="$PWD"
DIR2="$HOME"
# Take a file from $DIR1 and check for it in $DIR2
for i in $DIR1/*; do
HASH=$(md5sum $i 2>/dev/null | cut -d ' ' -f1 )
if [ "$HASH" ]; then
for j in $DIR2/*; do
HASH2=$(md5sum $j | cut -d ' ' -f1)
if [ "$HASH" = "$HASH2" ]; then
# Delete files from $DIR2
rm "$j"
fi
done
fi
done