比较和同步两个(巨大的)目录——只考虑文件名
Compare and sync two (huge) directories - consider only filenames
我想在 Linux 中的两个目录之间进行单向同步。一个包含文件,另一个包含 processed 个文件,但具有相同的目录结构和相同的文件名,但某些文件可能丢失。
现在我在做:
cd $SOURCE
find * -type f | while read fname; do
if [ ! -e "$TARGET$fname" ]
then
# process the file and copy it to the target. Create directories if needed.
fi
done
有效,但速度慢得令人痛苦。
有更好的方法吗?
大约有 50.000.000 个文件,分布在目录和子目录中。每个目录不超过255files/subdirs.
我看了
rsync
:似乎它总是进行大小或时间戳比较。这将导致每个文件都被标记为不同,因为处理需要一些时间并更改文件内容。
diff -qr
:无法弄清楚如何让它忽略文件大小和内容
编辑
有效假设:
- 仅对 directory/file 个名称进行比较
- 我们不关心文件元数据 and/or 属性(例如,大小、所有者、权限、date/time 最后修改等)
- 我们不关心可能驻留在目标目录中但在源目录中没有匹配文件的文件。这只是部分正确,但从源代码中删除的情况很少见,而且会大量发生,因此我将为此做一个特例。
假设:
- 仅对 directory/file 个名称进行比较
- 我们不关心文件元数据 and/or 属性(例如,大小、所有者、权限、date/time 最后修改等)
- 我们不关心可能驻留在目标目录中但在源目录中没有匹配文件的文件
我看不出有什么方法可以比较 2x 约 5000 万个条目的列表,但我们可以尝试消除 bash
循环解决方案的逐个条目方法...
一个想法:
# obtain sorted list of all $SOURCE files
srcfiles=$(mktemp)
cd "${SOURCE}"
find * -type f | sort > "${srcfiles}"
# obtain sorted list of all $TARGET files
tgtfiles=$(mktemp)
cd "${TARGET}"
find * -type f | sort > "${tgtfiles}"
# 'comm -23' => extract list of items that only exist in the first file - ${srcfiles}
missingfiles=$(mktemp)
comm -23 "${srcfiles}" "${tgtfiles}" > "${missingfiles}"
# process list of ${SOURCE}-only files
while read -r missingfile
do
process_and_copy "${missingfile}"
done < "${missingsfiles}"
'rm' -rf "${srcfiles}" "${tgtfiles}" "${missingfiles}"
此解决方案本质上(仍然)是串行的,因此如果 'lot' 丢失文件,则处理所述丢失文件的总时间可能会很可观。
如果有足够的系统资源(cpu、内存、磁盘吞吐量),'faster' 解决方案将着眼于并行化工作的方法,例如:
- 运行 不同
$SOURCE/$TARGET
子目录上的并行 find/sort/comm/process
线程(如果丢失文件的数量均匀分布在不同的子目录中,可能会很好地工作)或 ...
- 坚持使用串行
find/sort/comm
但 split
${missingfiles}
分成块,然后生成单独的 OS 进程到 process_and_copy
不同的块
我想在 Linux 中的两个目录之间进行单向同步。一个包含文件,另一个包含 processed 个文件,但具有相同的目录结构和相同的文件名,但某些文件可能丢失。
现在我在做:
cd $SOURCE
find * -type f | while read fname; do
if [ ! -e "$TARGET$fname" ]
then
# process the file and copy it to the target. Create directories if needed.
fi
done
有效,但速度慢得令人痛苦。 有更好的方法吗?
大约有 50.000.000 个文件,分布在目录和子目录中。每个目录不超过255files/subdirs.
我看了
rsync
:似乎它总是进行大小或时间戳比较。这将导致每个文件都被标记为不同,因为处理需要一些时间并更改文件内容。diff -qr
:无法弄清楚如何让它忽略文件大小和内容
编辑
有效假设:
- 仅对 directory/file 个名称进行比较
- 我们不关心文件元数据 and/or 属性(例如,大小、所有者、权限、date/time 最后修改等)
- 我们不关心可能驻留在目标目录中但在源目录中没有匹配文件的文件。这只是部分正确,但从源代码中删除的情况很少见,而且会大量发生,因此我将为此做一个特例。
假设:
- 仅对 directory/file 个名称进行比较
- 我们不关心文件元数据 and/or 属性(例如,大小、所有者、权限、date/time 最后修改等)
- 我们不关心可能驻留在目标目录中但在源目录中没有匹配文件的文件
我看不出有什么方法可以比较 2x 约 5000 万个条目的列表,但我们可以尝试消除 bash
循环解决方案的逐个条目方法...
一个想法:
# obtain sorted list of all $SOURCE files
srcfiles=$(mktemp)
cd "${SOURCE}"
find * -type f | sort > "${srcfiles}"
# obtain sorted list of all $TARGET files
tgtfiles=$(mktemp)
cd "${TARGET}"
find * -type f | sort > "${tgtfiles}"
# 'comm -23' => extract list of items that only exist in the first file - ${srcfiles}
missingfiles=$(mktemp)
comm -23 "${srcfiles}" "${tgtfiles}" > "${missingfiles}"
# process list of ${SOURCE}-only files
while read -r missingfile
do
process_and_copy "${missingfile}"
done < "${missingsfiles}"
'rm' -rf "${srcfiles}" "${tgtfiles}" "${missingfiles}"
此解决方案本质上(仍然)是串行的,因此如果 'lot' 丢失文件,则处理所述丢失文件的总时间可能会很可观。
如果有足够的系统资源(cpu、内存、磁盘吞吐量),'faster' 解决方案将着眼于并行化工作的方法,例如:
- 运行 不同
$SOURCE/$TARGET
子目录上的并行find/sort/comm/process
线程(如果丢失文件的数量均匀分布在不同的子目录中,可能会很好地工作)或 ... - 坚持使用串行
find/sort/comm
但split
${missingfiles}
分成块,然后生成单独的 OS 进程到process_and_copy
不同的块