首页 > 解决方案 > 如何就地从 tarball 中删除空目录

问题描述

我从一个 docker 镜像中提取了一个层,该镜像归档在一个名为 layer.tar 的文件中。我想从中删除空目录。

我不想解压缩然后重新打包该存档中的文件,我想保留原始信息,所以我想就地进行。

我知道如何从 tar 中删除文件,但我不知道任何简单的方法来就地删除空目录。

标签: bashshellgnutar

解决方案


让我们创建一个包含空目录a/b/c/的存档 t.tar :a/b/c/d/

mkdir -p dir
cd dir
mkdir -p a/b/c/d
mkdir -p 1/2/3/4
touch a/fil_ea a/b/file_ab # directory a/b/c and a/b/c/d are empty
touch 1/2/3/file_123 1/2/3/4/file_1234 # directories 1/2/3/4 not empty
tar cf ../t.tar a 1
cd ..

使用tar tf和一些过滤,我们可以提取 tar 存档中的目录和文件。然后对于其中的每个目录,tmpdirs我们可以使用简单的 grep 检查它是否有任何文件tmpfiles,然后使用--deletetar 选项删除这些目录:

tar tf t.tar | tee >(grep '/$' > tmpdirs) | grep -v '/$' > tmpfiles
cat tmpdirs | xargs -n1 -- sh -c 'grep -q "$1" tmpfiles || echo "$1"' -- \
  | tac \
  | xargs -- tar --delete -f t.tar

并不是说 tac 有点不需要,而是文件在 tar 中按字母顺序排序,因此当 tara/b/c/首先删除包含所有子目录的目录然后尝试删除a/b/c/d/目录时,它会失败并出现Not found in archive错误。tac是一种廉价的解决方法,因此 tar 首先删除a/b/c/d/然后a/b/c/.


推荐阅读