ストレージ内の gzip や bzip2 の圧縮済みファイルを xz に変換する
ストレージの容量が厳しくなってきたので以下のようなコマンド実行で gzip 等のアーカイブを xz に一括変換してくれるスクリプトを書いてみた。
find . -type f -name '*.gz' | xargs convert2xz
- user, group は root で実行した場合に引き継がれます。
- 同名の *.xz と *.gz が存在した場合は、タイムスタンプが違う場合だけ書き潰します。
#!/bin/sh # 圧縮ファイルを xz で再圧縮する処理。 which pv > /dev/null 2>&1 if [ $? -eq 0 ]; then PV="pv" else PV="" fi while [ $# -gt 0 ]; do FILE=$1 ; shift if [ ! -e "${FILE}" ]; then continue fi # 元ファイルの拡張子を取得する(大文字 -> 小文字変換込み) EXT=$( echo ${FILE##*.} | tr "[:upper:]" "[:lower:]" ) # 拡張子毎の展開プログラムを決定する。 case "${EXT}" in "gz" ) EXTCMD="zcat" ;; "bz2" ) EXTCMD="bzcat" ;; "tgz" ) EXTCMD="zcat" ;; "tbz" ) EXTCMD="tbz" ;; * ) EXTCMD="" ;; esac case "${EXT}" in "gz" ) EXTCMD="zcat"; EXT_XZ="xz" ;; "bz2" ) EXTCMD="bzcat"; EXT_XZ="xz" ;; "tgz" ) EXTCMD="zcat"; EXT_XZ="txz" ;; "tbz" ) EXTCMD="bzcat"; EXT_XZ="txz" ;; "xz" ) continue ;; "txz" ) continue ;; * ) EXTCMD=""; EXT_XZ="xz" ;; esac echo "$FILE " if [ "${EXTCMD}" == "" ]; then # 展開用プログラムが不定の場合は処理対象外。 echo "ignore" else # 実行フラグを立てる(途中の処理でこれを落とす場合あり) EXEC_XZ_FLAG=1 # 元ファイル名の拡張子を .xz に変更したファイル名を作る FILE_XZ=${FILE%.${EXT}}.$EXT_XZ # .xz なファイルが存在している場合は # タイムスタンプが違う場合だけ処理対象とする。 if [ -e $FILE_XZ ]; then TIMESTAMP_ORG=$( date --reference=$FILE +"%s" ) TIMESTAMP_DST=$( date --reference=$FILE_XZ +"%s" ) echo $TIMESTAMP_ORG echo $TIMESTAMP_DST if [ $TIMESTAMP_ORG -eq $TIMESTAMP_DST ]; then $EXEC_XZ_FLAG=0 fi fi # 実行フラグが立っていたら再圧縮処理を実施 if [ $EXEC_XZ_FLAG -eq 0 ]; then echo "skip: already compressed." else trap "rm -f $FILE_XZ ; exit 1" 0 1 2 3 13 15 if [ "${PV}" == "" ]; then $EXTCMD $FILE | xz -v > $FILE_XZ else pv $FILE | $EXTCMD | xz > $FILE_XZ fi trap "exit 1" 0 1 2 3 13 15 fi # 再圧縮前後の状態の md5sum を比較し、 # 合致した場合はオリジナルを消す。 # 合致しない場合は xz 形式のファイルを消す。 tmpfile=$( mktemp ) trap "rm -f $tmpfile ; exit 1" 0 1 2 3 13 15 $EXTCMD $FILE | md5sum > $tmpfile xzcat $FILE_XZ | md5sum --quiet --check $tmpfile if [ $? -eq 0 ]; then touch --reference=$FILE $FILE_XZ chmod --reference=$FILE $FILE_XZ owner_orig=$( stat --printf="%u" $FILE ) if [ ${UID} -eq $owner_orig ]; then # このスクリプトの実行ユーザと元ファイルの owner が # 一致する場合は、group を元ファイルに合わせる。 chgrp --reference=$FILE $FILE_XZ elif [ ${UID} -eq 0 ]; then # このスクリプトの実行ユーザが root の場合は # owner , group を元ファイルに合わせる。 chown --reference=$FILE $FILE_XZ chgrp --reference=$FILE $FILE_XZ fi echo -n "${FILE##*/} " stat --printf="%s byte -> " $FILE stat --printf="%s byte\n\n" $FILE_XZ rm -f $FILE else if [ $EXEC_XZ_FLAG -ne 0 ]; then rm -f $FILE_XZ fi fi rm $( mktemp ) trap "exit 1" 0 1 2 3 13 15 fi done