除了自动执行您概述的步骤之外,不会有太多选择,原因是答案中的警告所证明的Kimvais https://stackoverflow.com/users/180174/kimvais.
tar 修改操作
The tar
命令有一些选项可以修改现有的 tar 文件。然而,由于多种原因,它们不适合您的场景,其中之一是需要编辑的是嵌套 tarball,而不是主 tarball。因此,您必须亲自完成这项工作。
假设
主存档中的所有存档是否都提取到当前目录或命名/创建的子目录中?也就是说,当你跑步时tar -tf master.tar.gz
, 你有看到:
subdir-1.23/tarball1.tar
subdir-1.23/tarball2.tar
...
或者你看到:
tarball1.tar
tarball2.tar
(请注意,如果要嵌入更大的压缩 tarball 中,则嵌套 tar 本身不应被 gzip 压缩。)
主控重新打包程序
假设您有子目录符号,那么您可以执行以下操作:
for master in "$@"
do
tmp=$(pwd)/xyz.$$
trap "rm -fr $tmp; exit 1" 0 1 2 3 13 15
cat $master |
(
mkdir $tmp
cd $tmp
tar -xf -
cd * # There is only one directory in the newly created one!
process_tarballs *
cd ..
tar -czf - * # There is only one directory down here
) > new.$master
rm -fr $tmp
trap 0
done
如果您在恶意环境中工作,请使用除tmp.$$
为目录名称。然而,这种重新打包通常不会在恶意环境中进行,并且基于进程 ID 选择的名称足以为所有内容提供唯一的名称。指某东西的用途tar -f -
输入和输出允许您切换目录,但仍然在命令行上处理相对路径名。如果您愿意,可能还有其他方法可以解决这个问题。我也用过cat
将输入提供给子 shell,以便从上到下的流程清晰;从技术上讲,我可以通过使用来改进事情) > new.$master < $master
在最后,但这隐藏了多行之后的一些关键信息。
trap 命令确保 (a) 如果脚本被中断(发出 HUP、INT、QUIT、PIPE 或 TERM 信号),临时目录将被删除并且退出状态为 1(不成功),并且 (b) 一旦子目录被删除,删除后,进程可以以零状态退出。
您可能需要在覆盖 new.$master 之前检查它是否存在。您可能需要检查提取操作是否确实提取了内容。您可能需要检查子压缩包处理是否确实有效。如果主 tarball 解压到多个子目录中,则需要将 'cd *
' 进入某个循环,迭代它创建的子目录。
如果您对内容足够了解并且没有出现任何问题,那么所有这些问题都可以跳过。
进程压缩包
第二个脚本是process_tarballs;它依次在命令行上处理每个 tarball,提取文件、进行替换、重新打包结果等。使用两个脚本的一个优点是,您可以将 tarball 处理与处理一个更大的任务分开进行测试。包含多个 tarball 的 tarball。同样,如果每个子 tarball 都解压到自己的子目录中,生活会变得更加容易;如果其中任何一个解压到当前目录中,请确保为其创建一个新的子目录。
for tarball in "$@"
do
# Extract $tarball into sub-directory
tar -xf $tarball
# Locate appropriate sub-directory.
(
cd $subdirectory
find . -type f -print0 | xargs -0 sed -i 's/name/alternative-name/g'
)
mv $tarball old.$tarball
tar -cf $tarball $subdirectory
rm -f old.$tarball
done
您也应该在此处添加陷阱进行清理,以便该脚本可以与上面的主脚本隔离运行,并且仍然不会留下任何中间目录。在外部脚本的上下文中,您可能不需要在创建新 tarball 之前如此小心地保留旧 tarball(因此rm -f $tarbal
而不是移动和删除命令),但按照其本身的权利处理,脚本应该小心不要损坏任何东西。
Summary
- 你正在尝试的事情并不是微不足道的。
- 可调试性将作业分成两个可以独立测试的脚本。
- 当您知道文件中的实际内容时,处理极端情况就会容易得多。