从 tarball 中删除目录的跨平台方法
Cross-platform way to remove dir from tarball
我发现了这个:
https://www.cyberciti.biz/faq/unix-linux-appleosx-bsd-tar-remove-directory/
tar --delete -f file.tar 'path1/dir1'
但这在 MacOS 上不起作用。我得到:
tar: Option --delete is not supported
我正在寻找适用于所有 *nix 风格的东西。有人知道这样做的好方法吗?也许我真的需要先解压并忽略该文件夹,然后重新压缩它?
简答
是的,如果您想要一个适用于许多 *nix flavors 的解决方案,那么您将不得不这样做;先解压,忽略文件夹,然后重新打包。
解决方案:
我会做如下事情:
# Path to source .tar
src_tar=/the/path/to/your/tarfile.tar
# Path to dir in .tar that you want to delete.
rm_tar_dir=path1/dir1
# Create a temporary dir for extracting the .tar contents into.
tmp_dir=$(mktemp -d 2>/dev/null || mktemp -d -t 'tar-tmpdir')
# Extract all contents from the source .tar to a temporary dir
tar zxf "$src_tar" -C "$tmp_dir"
# Delete the unwanted dir from temporary dir.
rm -rf "${tmp_dir:?}/${rm_tar_dir}"
# Create new .tar archive, overwriting the original source .tar
tar czf "$src_tar" -C "$tmp_dir" .
# Clean up
rm -rf "$tmp_dir"
为什么我推荐上面显示的解决方案:
首先,(出于显而易见的原因)我无法测试并确认上述解决方案在所有 *nix flavors 上都能成功运行。其次,如果我不这么说就太天真了,因为(我相信你知道),这是一个古老的大景观,即有很多版本、口味和变体。
我根据以下 findings/research 得出了上面建议的解决方案。 *nix 的风格在下面的 support/compatibility table 中涵盖的远非详尽无遗。我从 here.
列出的口味中选择了它们
大多数选择的 flavours 是由志愿者团体开发的,并免费提供(Open BSD、Free BSD 等)。幸运的是,这些 *nix 风格 的文档、手册页等已在线发布,它们对我的决策产生了主要影响。 IBM AIX 和 Sun 的 Solaris 是例外,因为它们是专有的,但是这两者有一些文档、手册页等。
Support/Compatibility 表
tar --delete
选项
让我们先看看对 tar
命令 --delete
选项的支持。正如您在下面的 table 中看到的那样,它远未得到广泛支持 :(
因此,为什么似乎有必要采用更详细的解决方案 - 不幸的是,当需要跨平台时,我们不能使用 oneliner .
┌─────┬──────┬──────┬─────┬──────────────┬───────┬─────────┐
│ IBM │ Open │ Free │ Net │ Darwin/MacOS │ Linux │ Sun │
│ AIX │ BSD │ BSD │ BSD │ BSD │ GNU │ Solaris │
┌─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤
│ --delete │ x │ x │ x │ √ │ x │ √ │ x │
└─────────────┴─────┴──────┴──────┴─────┴──────────────┴───────┴─────────┘
其他tar
选项
上面提供的解决方案使用了几个 tar
选项,即; -z
、-x
、-f
、-c
和 -C
。正如您在下面的 table 中看到的那样,它们得到了广泛的支持。但是,值得注意的是 -z
选项(用于通过 gzip 过滤存档)在 IBM 的 AIX 上不受支持,据我所知,它在大型机上使用 -(因此,我的假设可能不是很多对你来说是一个破坏者。
┌─────┬──────┬──────┬─────┬──────────────┬───────┬─────────┐
│ IBM │ Open │ Free │ Net │ Darwin/MacOS │ Linux │ Sun │
│ AIX │ BSD │ BSD │ BSD │ BSD │ GNU │ Solaris │
┌─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤
│ -z │ x │ √ │ √ │ √ │ √ │ √ │ √ │
├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤
│ -x │ √ │ √ │ √ │ √ │ √ │ √ │ √ │
├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤
│ -f │ √ │ √ │ √ │ √ │ √ │ √ │ √ │
├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤
│ -c │ √ │ √ │ √ │ √ │ √ │ √ │ √ │
├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤
│ -C │ √ │ √ │ √ │ √ │ √ │ √ │ √ │
├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤
│ --exclude │ x │ x │ √ │ √ │ √ │ √ │ x │
└─────────────┴─────┴──────┴──────┴─────┴──────────────┴───────┴─────────┘
tar --exclude
选项
请注意,在之前的 table 中,--exclude
选项似乎也没有得到广泛支持 - 因此我们不在建议的解决方案中使用它。在解压 .tar
时,我会避免选择排除不需要的目录(即您要删除的目录)。所以避免做这样的事情:
# Don't do this....
# Extract all contents from the source .tar to a temporary dir,
# and exclude the directory that you effectively want to delete.
tar zxf "path/to/tarfile.tar" --exclude "path1/dir1" -C "path/to/tmpdir"
您会注意到在建议的解决方案中,我们解压所有内容(不排除),然后使用 rm -rf
删除不需要的目录,然后再重新打包。
解决方案使用的其他命令
下面的 table 显示了建议解决方案中使用的其余命令:
┌─────┬──────┬──────┬─────┬──────────────┬───────┬─────────┐
│ IBM │ Open │ Free │ Net │ Darwin/MacOS │ Linux │ Sun │
│ AIX │ BSD │ BSD │ BSD │ BSD │ GNU │ Solaris │
┌─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤
│ rm -rf │ √ │ √ │ √ │ √ │ √ │ √ │ √ │
├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤
│ mktemp │ x │ √ │ ? │ √ │ √ │ √ │ √ │
├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤
│ mktemp -d │ x │ √ │ ? │ √ │ √ │ √ │ √ │
├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤
│ mktemp -t │ x │ √ │ ? │ √ │ √ │ √ │ √ │
└─────────────┴─────┴──────┴──────┴─────┴──────────────┴───────┴─────────┘
如您所见,我们很好地利用了 rm -rf
,因为它得到了很好的支持。
谨慎mktemp
...
mktemp
和它的 -t
和 -d
选项似乎没有得到广泛支持。 (注意:我不确定 Free BSD 是否支持它 - 因此 ?
指示符)。
因此,虽然我建议的解决方案确实使用了 mktemp
,但您可能希望改用 mkdir -p
,因为它得到广泛支持,如下面的 table:
┌─────┬──────┬──────┬─────┬──────────────┬───────┬─────────┐
│ IBM │ Open │ Free │ Net │ Darwin/MacOS │ Linux │ Sun │
│ AIX │ BSD │ BSD │ BSD │ BSD │ GNU │ Solaris │
┌─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤
│ mkdir -p │ √ │ √ │ √ │ √ │ √ │ √ │ √ │
└─────────────┴─────┴──────┴──────┴─────┴──────────────┴───────┴─────────┘
参考资料
以下参考资料用于总结建议的解决方案,并编译兼容性 tables:
tar
mktemp -d -t
rm -rf
mkdir -p
其他
我发现了这个: https://www.cyberciti.biz/faq/unix-linux-appleosx-bsd-tar-remove-directory/
tar --delete -f file.tar 'path1/dir1'
但这在 MacOS 上不起作用。我得到:
tar: Option --delete is not supported
我正在寻找适用于所有 *nix 风格的东西。有人知道这样做的好方法吗?也许我真的需要先解压并忽略该文件夹,然后重新压缩它?
简答
是的,如果您想要一个适用于许多 *nix flavors 的解决方案,那么您将不得不这样做;先解压,忽略文件夹,然后重新打包。
解决方案:
我会做如下事情:
# Path to source .tar
src_tar=/the/path/to/your/tarfile.tar
# Path to dir in .tar that you want to delete.
rm_tar_dir=path1/dir1
# Create a temporary dir for extracting the .tar contents into.
tmp_dir=$(mktemp -d 2>/dev/null || mktemp -d -t 'tar-tmpdir')
# Extract all contents from the source .tar to a temporary dir
tar zxf "$src_tar" -C "$tmp_dir"
# Delete the unwanted dir from temporary dir.
rm -rf "${tmp_dir:?}/${rm_tar_dir}"
# Create new .tar archive, overwriting the original source .tar
tar czf "$src_tar" -C "$tmp_dir" .
# Clean up
rm -rf "$tmp_dir"
为什么我推荐上面显示的解决方案:
首先,(出于显而易见的原因)我无法测试并确认上述解决方案在所有 *nix flavors 上都能成功运行。其次,如果我不这么说就太天真了,因为(我相信你知道),这是一个古老的大景观,即有很多版本、口味和变体。
我根据以下 findings/research 得出了上面建议的解决方案。 *nix 的风格在下面的 support/compatibility table 中涵盖的远非详尽无遗。我从 here.
列出的口味中选择了它们大多数选择的 flavours 是由志愿者团体开发的,并免费提供(Open BSD、Free BSD 等)。幸运的是,这些 *nix 风格 的文档、手册页等已在线发布,它们对我的决策产生了主要影响。 IBM AIX 和 Sun 的 Solaris 是例外,因为它们是专有的,但是这两者有一些文档、手册页等。
Support/Compatibility 表
tar --delete
选项让我们先看看对
tar
命令--delete
选项的支持。正如您在下面的 table 中看到的那样,它远未得到广泛支持:(
因此,为什么似乎有必要采用更详细的解决方案 - 不幸的是,当需要跨平台时,我们不能使用 oneliner .┌─────┬──────┬──────┬─────┬──────────────┬───────┬─────────┐ │ IBM │ Open │ Free │ Net │ Darwin/MacOS │ Linux │ Sun │ │ AIX │ BSD │ BSD │ BSD │ BSD │ GNU │ Solaris │ ┌─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤ │ --delete │ x │ x │ x │ √ │ x │ √ │ x │ └─────────────┴─────┴──────┴──────┴─────┴──────────────┴───────┴─────────┘
其他
tar
选项上面提供的解决方案使用了几个
tar
选项,即;-z
、-x
、-f
、-c
和-C
。正如您在下面的 table 中看到的那样,它们得到了广泛的支持。但是,值得注意的是-z
选项(用于通过 gzip 过滤存档)在 IBM 的 AIX 上不受支持,据我所知,它在大型机上使用 -(因此,我的假设可能不是很多对你来说是一个破坏者。┌─────┬──────┬──────┬─────┬──────────────┬───────┬─────────┐ │ IBM │ Open │ Free │ Net │ Darwin/MacOS │ Linux │ Sun │ │ AIX │ BSD │ BSD │ BSD │ BSD │ GNU │ Solaris │ ┌─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤ │ -z │ x │ √ │ √ │ √ │ √ │ √ │ √ │ ├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤ │ -x │ √ │ √ │ √ │ √ │ √ │ √ │ √ │ ├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤ │ -f │ √ │ √ │ √ │ √ │ √ │ √ │ √ │ ├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤ │ -c │ √ │ √ │ √ │ √ │ √ │ √ │ √ │ ├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤ │ -C │ √ │ √ │ √ │ √ │ √ │ √ │ √ │ ├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤ │ --exclude │ x │ x │ √ │ √ │ √ │ √ │ x │ └─────────────┴─────┴──────┴──────┴─────┴──────────────┴───────┴─────────┘
tar --exclude
选项请注意,在之前的 table 中,
--exclude
选项似乎也没有得到广泛支持 - 因此我们不在建议的解决方案中使用它。在解压.tar
时,我会避免选择排除不需要的目录(即您要删除的目录)。所以避免做这样的事情:# Don't do this.... # Extract all contents from the source .tar to a temporary dir, # and exclude the directory that you effectively want to delete. tar zxf "path/to/tarfile.tar" --exclude "path1/dir1" -C "path/to/tmpdir"
您会注意到在建议的解决方案中,我们解压所有内容(不排除),然后使用
rm -rf
删除不需要的目录,然后再重新打包。
解决方案使用的其他命令
下面的 table 显示了建议解决方案中使用的其余命令:
┌─────┬──────┬──────┬─────┬──────────────┬───────┬─────────┐ │ IBM │ Open │ Free │ Net │ Darwin/MacOS │ Linux │ Sun │ │ AIX │ BSD │ BSD │ BSD │ BSD │ GNU │ Solaris │ ┌─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤ │ rm -rf │ √ │ √ │ √ │ √ │ √ │ √ │ √ │ ├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤ │ mktemp │ x │ √ │ ? │ √ │ √ │ √ │ √ │ ├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤ │ mktemp -d │ x │ √ │ ? │ √ │ √ │ √ │ √ │ ├─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤ │ mktemp -t │ x │ √ │ ? │ √ │ √ │ √ │ √ │ └─────────────┴─────┴──────┴──────┴─────┴──────────────┴───────┴─────────┘
如您所见,我们很好地利用了
rm -rf
,因为它得到了很好的支持。谨慎
mktemp
...mktemp
和它的-t
和-d
选项似乎没有得到广泛支持。 (注意:我不确定 Free BSD 是否支持它 - 因此?
指示符)。因此,虽然我建议的解决方案确实使用了
mktemp
,但您可能希望改用mkdir -p
,因为它得到广泛支持,如下面的 table:┌─────┬──────┬──────┬─────┬──────────────┬───────┬─────────┐ │ IBM │ Open │ Free │ Net │ Darwin/MacOS │ Linux │ Sun │ │ AIX │ BSD │ BSD │ BSD │ BSD │ GNU │ Solaris │ ┌─────────────┼─────┼──────┼──────┼─────┼──────────────┼───────┼─────────┤ │ mkdir -p │ √ │ √ │ √ │ √ │ √ │ √ │ √ │ └─────────────┴─────┴──────┴──────┴─────┴──────────────┴───────┴─────────┘
参考资料
以下参考资料用于总结建议的解决方案,并编译兼容性 tables:
tar
mktemp -d -t
rm -rf
mkdir -p
其他