Gre*_*hal 4 linux compression tar bzip2
有没有办法把一个叫dir1的目录变成dir1.tar.bz2而不保留原来的?我需要节省空间并想压缩一些大文件,但没有足够的空间来保存压缩副本和原始文件。有没有办法直接将现有文件转换为存档?
tar 不能这样做,但您可以通过以下方式实现您想要的:
find dir1 -depth -print0 | xargs -0 tar --create --no-recursion --remove-file --file - | bzip2 > dir1.tar.bz2
在哪里:
find dir1 -depth -print0
列出 中的所有文件和目录dir1,在目录本身之前列出目录内容 ( -depth)。使用的-print0(和-0在xargs下面)的关键在于带空格支持目录和文件名。
xargs -0 tar --create --no-recursion --remove-file --file -
创建一个 tar 存档并将每个文件或目录添加到其中。tar 存档通过选项发送到标准输出--file -。
bzip2 > dir1.tar.bz2
将 tar 存档从标准输入压缩到一个名为dir1.tar.bz2.
所需的可用磁盘空间量是 中最大压缩文件的大小,dir1因为tar在处理文件时,会等到归档完成后再删除它。由于在短时间内通过tar管道传输到bzip2,然后tar将其删除,因此每个文件都驻留在两个位置:未压缩在文件系统中和压缩在dir1.tar.bz2.
我很想知道磁盘空间是如何使用的,所以我在我的 Ubuntu VM 上做了这个实验:
创建一个 1 GB 的文件系统:
$ dd if=/dev/zero of=/tmp/1gb bs=1M count=1024
$ losetup /dev/loop0 /tmp/1gb
$ mkfs.ext3 /dev/loop0
$ sudo mount /dev/loop0 /tmp/mnt
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/loop0 1008M 34M 924M 4% /tmp/mnt
Run Code Online (Sandbox Code Playgroud)用 900 个 1 兆字节的文件填充文件系统:
$ chown jaume /tmp/mnt
$ mkdir /tmp/mnt/dir1
$ for (( i=0; i<900; i++ )); do dd if=/dev/urandom of=/tmp/mnt/dir1/file$i bs=1M count=1; done
$ chown -R jaume /tmp/mnt
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/loop0 1008M 937M 20M 98% /tmp/mnt
Run Code Online (Sandbox Code Playgroud)
文件系统现在已满 98%。
复制一份dir1供以后验证:
$ cp -a /tmp/mnt/dir1 /tmp/dir1-check
Run Code Online (Sandbox Code Playgroud)压缩dir1:
$ ls /tmp/mnt
dir1 lost+found
$ find /tmp/mnt/dir1 -depth -print0 | xargs -0 tar --create --no-recursion --remove-file --file - | bzip2 > /tmp/mnt/dir1.tar.bz2
$
Run Code Online (Sandbox Code Playgroud)
请注意,命令运行时没有任何“设备上没有剩余空间”错误。
dir1被移除,只dir1.tar.bz2存在:
$ ls /tmp/mnt
dir1.tar.bz2 lost+found
Run Code Online (Sandbox Code Playgroud)展开dir1.tar.bz2并比较/tmp/dir1-check:
$ tar --extract --file dir1.tar.bz2 --bzip2 --directory /tmp
$ diff -s /tmp/dir1 /tmp/dir1-check
(...)
Files /tmp/dir1/file97 and /tmp/dir1-check/file97 are identical
Files /tmp/dir1/file98 and /tmp/dir1-check/file98 are identical
Files /tmp/dir1/file99 and /tmp/dir1-check/file99 are identical
$
Run Code Online (Sandbox Code Playgroud)
副本dir1和解压dir1.tar.bz2是一样的!
这可以在脚本中概括:
tarrm使用以下内容创建一个名为(或您喜欢的任何其他名称)的文件:
#!/bin/bash
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
# dir is first argument
dir="$1"
# check dir exists
if [ ! -d "$dir" ]; then
echo "$(basename $0): error: '$dir' doesn't exist" 1>&2
exit 1
fi
# check if tar file exists
if [ -f "${dir}.tar" -o -f "${dir}.tar.bz2" ]; then
echo "$(basename $0): error: '$dir.tar' or '${dir}.tar.bz2' already exist" 1>&2
exit 1
fi
# --keep is second argument
if [ "X$2" == "X--keep" ]; then
# keep mode
removefile=""
echo " Tarring '$dir'"
else
removefile="--remove-file"
echo " Tarring and **deleting** '$dir'"
fi
# normalize directory name (for example, /home/jaume//// is a legal directory name, but will break ${dir}.tar.bz2 - it needs to be converted to /home/jaume)
dir=$(dirname "$dir")/$(basename "$dir")
# create compressed tar archive and delete files after adding them to it
find "$dir" -depth -print0 | xargs -0 tar --create --no-recursion $removefile --file - | bzip2 > "${dir}.tar.bz2"
# return status of last executed command
if [ $? -ne 0 ]; then
echo "$(basename $0): error while creating '${dir}.tar.bz2'" 1>&2
fi
Run Code Online (Sandbox Code Playgroud)使其可执行:
chmod a+x tarrm
该脚本做一些基本的错误检查:dir1必须存在,dir1.tar.bz2并且dir1.tar不应该存在,具有保持模式。它还支持带有嵌入空格的目录和文件名。
我已经测试了脚本,但不能保证它是完美的,所以首先在保持模式下使用它:
./tarrm dir1 --keep
这个调用将添加dir1到dir1.tar.bz2,但不会删除该目录。
当您信任脚本时,请像这样使用它:
./tarrm dir1
脚本会通知你dir1在tarring的过程中会被删除:
Tarring and **deleting** 'dir1'
例如:
$ ls -lF
total 4
drwxrwxr-x 3 jaume jaume 4096 2013-10-11 11:00 dir 1/
$ find "dir 1"
dir 1
dir 1/subdir 1
dir 1/subdir 1/file 1
dir 1/file 1
$ /tmp/tarrm dir\ 1/
Tarring and **deleting** 'dir 1/'
$ echo $?
0
$ ls -lF
total 4
-rw-rw-r-- 1 jaume jaume 181 2013-10-11 11:00 dir 1.tar.bz2
$ tar --list --file dir\ 1.tar.bz2
dir 1/subdir 1/file 1
dir 1/subdir 1/
dir 1/file 1
dir 1/
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6166 次 |
| 最近记录: |