TAR 简单地将原始文件内容与一些元数据混合在一起进行连接。正如您所注意到的那样,更新文件只是将文件附加到 TAR 的末尾,并且按照惯例,出现在 TAR 中的最后一个文件会“胜出”。TAR 不仅仅是更新文件,因为这可能意味着所有更新后的文件内容都必须向后移动一些字节来为更大的新文件版本腾出空间。
实际上,这里没有提到的有一个适合您用例的 TAR 选项:
--occurrence=[NUMBER]
。使用此选项,您可以指定要提取或删除的具有相同名称/路径的多个文件版本中的哪一个。它将在您的简单示例中正常工作。这是我设置它的方式:
echo foo > test1.txt
echo foo > test2.txt
tar -cf updated.tar test1.txt test2.txt
sleep 1s
echo barbara > test2.txt
tar --update -f updated.tar test1.txt test2.txt
sleep 1s
echo foobar > test2.txt
tar --update -f updated.tar test1.txt test2.txt
tar tvlf updated.tar
-rwx------ user/group 4 2022-03-29 19:00 test1.txt
-rwx------ user/group 4 2022-03-29 19:00 test2.txt
-rwx------ user/group 8 2022-03-29 19:01 test2.txt
-rwx------ user/group 7 2022-03-29 19:01 test2.txt
请注意,
tar --update
只会检查时间戳而不是内容,时间戳只有1秒的精度!因此,我们需要等待1秒钟以确保时间戳至少比现有文件晚1秒,否则
tar
将不会将其添加到存档中。当复制粘贴此代码时,这一点尤为重要。
简单地调用
--delete
将删除
所有版本:
tar --delete -f updated.tar test2.txt
tar tvlf updated.tar
-rwx------ user/group 4 2022-03-29 19:00 test1.txt
当指定 --occurrence=1
时,只会删除第一次出现的,即最旧的版本:
tar --delete -f updated.tar test2.txt
tar tvlf updated.tar
-rwx------ user/group 4 2022-03-29 19:00 test1.txt
-rwx------ user/group 8 2022-03-29 19:01 test2.txt
-rwx------ user/group 7 2022-03-29 19:01 test2.txt
很遗憾,对于
--delete
选项,您只能删除一个文件版本。因此,您需要重复删除最旧的版本,直到只剩下最新的版本为止。虽然可以在bash中完成此操作,这至少比将其提取到临时文件夹中更加节省空间,但可能会更慢,因为它必须多次扫描归档文件,每次扫描归档文件时基本上会完全重写归档文件。
我建议使用我编写的
ratarmount
代替。它将挂载存档文件(而不是实际提取),并公开一个文件夹视图,显示每个文件的最新版本。使用此方法,您可以创建新的精简存档文件:
python3 -m pip install --user ratarmount
ratarmount updated.tar
ls -lA updated/
-rwx------ 1 user group 4 Mar 29 19:14 test1.txt
-rwx------ 1 user group 7 Mar 29 19:14 test2.txt
tar -c -f most-recent.tar -C updated/ .
tar tvlf updated.tar
drwxrwxrwx user/group 0 2022-03-29 19:00 ./
-rwx------ user/group 4 2022-03-29 19:00 ./test1.txt
-rwx------ user/group 7 2022-03-29 19:01 ./test2.txt
这就是全部内容。使用 -C
并指定归档.
文件夹,导致tar tvlf
的输出与前面的点略有不同。通常情况下,这没有问题,但您可以通过以下任何一种稍微更具问题性的选项来避免这种情况:
tar -c -f most-recent.tar -C updated/ test1.txt test2.txt
tar -c -f most-recent.tar -C updated/ $( cd updated && find . -mindepth 1 -maxdepth 1 )
( cd updated/ && tar -c -f ../most-recent.tar {[^.],.[!.],..?}*; )
如果您在使用ratarmount时遇到问题,请在这里提交问题。
请注意,ratarmount甚至会在特殊的隐藏文件夹中公开那些较旧的版本:
ratarmount updated.tar
ls -lA updated/test2.txt.versions/
-rwx------ 1 user group 4 Mar 29 20:10 1
-rwx------ 1 user group 8 Mar 29 20:10 2
-rwx------ 1 user group 7 Mar 29 20:10 3
特殊的.versions
文件夹中的文件名与给定的--occurrence
参数匹配。
在bash中,上述提到的使用--occurrence
的版本如下:
function deleteAllButMostRecentInTar()
{
local archive=$1
local filesToDelete=$( mktemp )
while true; do
tar --list --file "$archive" | sort | uniq -c |
sed -n -E '/^[ \t]*1 /d; s|^[ \t]*[0-9]+ ||p' > "$filesToDelete"
if [[ -s "$filesToDelete" ]]; then
local fileCount=$( cat -- "$filesToDelete" | wc -l )
echo -n "Found $fileCount files with more than version. Deleting ..."
tar --delete --occurrence=1 --files-from="$filesToDelete" \
--file "$archive"
echo " OK"
else
break
fi
done
rm -- "$filesToDelete"
echo
}
deleteAllButMostRecentInTar updated.tar
tar tvlf updated.tar
-rwx------ user/group 4 2022-03-29 19:00 test1.txt
-rwx------ user/group 7 2022-03-29 19:01 test2.txt
tar
命令中没有替换文件的选项。我建议在添加新文件之前删除现有文件。如果您正在运行GNU tar,请使用--delete
。 - Digvijay S--update
更新的是 TAR 文件,而不是 TAR 文件中的文件。因此它按设计工作。 - Nic3500zip
可以做到。 - Fravadona