元のディレクトリを保持せずに、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
(および以下のxargs
の-0
)の使用は、スペースが埋め込まれたディレクトリ名とファイル名をサポートするの鍵です。
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
内で圧縮された2つの場所に存在します。 。
ディスクスペースがどのように使用されているか知りたいので、UbuntuVMでこの実験を行いました。
1GBのファイルシステムを作成します。
$ 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
ファイルシステムを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
ファイルシステムは98%いっぱいになりました。
後で確認するために、dir1
のコピーを作成します。
$ cp -a /tmp/mnt/dir1 /tmp/dir1-check
圧縮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
$
コマンドは「デバイスにスペースが残っていない」エラーなしで実行されたことに注意してください。
dir1
が削除され、dir1.tar.bz2
のみが存在します:
$ ls /tmp/mnt
dir1.tar.bz2 lost+found
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
$
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
実行可能にする:
chmod a+x tarrm
スクリプトはいくつかの基本的なエラーチェックを行います。dir1
が存在する必要があり、dir1.tar.bz2
とdir1.tar
が存在してはならず、keepモード。また、スペースが埋め込まれたディレクトリ名とファイル名もサポートしています。
スクリプトをテストしましたが、完璧であるとは保証できませんなので、最初にキープモードで使用します。
./tarrm dir1 --keep
この呼び出しにより、dir1
がdir1.tar.bz2
に追加されますが、ディレクトリは削除されません。
スクリプトを信頼する場合は、次のように使用してください。
./tarrm dir1
スクリプトは、タールを塗る過程でdir1
が削除されることを通知します。
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/