如何在 Linux 中使用一个命令将文件压缩并复制到另一个文件夹并保持其目录结构?
例如,我有:
/dir1
/dir1/file1.fit
/dir1/file2.fit
/dir1/file3.fit
/dir1/dir2/file1.fit
/dir1/dir2/file2.fit
/dir1/dir2/file3.fit
在我使用命令后(假设我复制/dir1
到/another_dir
),我想得到:
/another_dir/dir1
/another_dir/dir1/file1.fit.gz
/another_dir/dir1/file2.fit.gz
/another_dir/dir1/file3.fit.gz
/another_dir/dir1/dir2/file1.fit.gz
/another_dir/dir1/dir2/file2.fit.gz
/another_dir/dir1/dir2/file3.fit.gz
这/another_dir
实际上是另一个硬盘。由于此目标驱动器中没有足够的空间(这是 2TB 的数据!),请不要建议我先复制文件,然后再 gzip all(反之亦然)。同样,操作后 gz 文件不应保留在源文件夹中。
答案1
假设您位于根文件夹中,其中包含所有用于压缩的目录(在您的情况下/
),您可以find
与xargs
命令一起使用,例如
find dir1/ -name "*.fit" -print0 | xargs -i% -r0 sh -c 'mkdir -vp "$(dirname "/another_dir/%")" && gzip -vc "%" | tee "/another_dir/%".gz > /dev/null && rm -v "%"'
注意:您也可以替换| tee "/another_dir/%".gz > /dev/null
为> "/another_dir/%".gz
.
这将找到其中的所有.fit
文件dir1/
并将它们传递给xargs
解析命令,其中%
替换为每个文件。
该xargs
命令将:
- 创建空文件夹 (
mkdir
) 及其parents (-p
) 作为占位符, - 将给定文件 (
%
) 压缩到标准输出 (-c
) 并将压缩输出重定向到tee
, tee
将把压缩的输入保存到.gz
文件中(因为tee
默认情况下将输入打印到终端屏幕,将其发送到/dev/null
将抑制它,但它仍然会将内容保存到给定文件中)。
压缩成功后,删除原来的( rm
)。您始终可以删除该部分,以便在验证压缩文件后手动删除它们。
重要的是,您位于 的相对文件夹中dir1/
,因此返回的所有路径都find
相对于当前文件夹,因此您不必将绝对路径转换为相对路径realpath
(这仍然可以通过例如来完成realpath --relative-to=$absolute $current
,但它只会使上述命令变得过于复杂)。
在 macOS 上,要使用 的-r
参数xargs
,您需要安装 GNU xargs
( brew install xargs
) 并改用gxargs
命令。其他 BSD 系统上类似。
相关问题:gzip 不同目录中的多个文件并复制到新目录。
答案2
我不知道单个命令可以做到这一点,但是在 ServerFault 上是实现相同功能的简单脚本的示例。请注意,它不会保留文件权限或访问/修改时间,并且如果文件名包含空格或类似内容,则可能会出现问题。