web-dev-qa-db-ja.com

異なるディレクトリにあるいくつかのファイルをgzipで圧縮し、新しいディレクトリにコピーします

個々の.gzファイルに圧縮する必要がある異なるディレクトリにあるいくつかのファイルを使用しています。また、元のファイルはそのままにして、圧縮ファイルを1つのディレクトリに移動する必要があります。

Gzipコマンドと、圧縮するファイルのすべてのファイルパスのリストを含むファイルを使用してこれを行う方法はありますか?

それが少し長すぎる場合はお詫びします...私はLinuxにかなり慣れていないので、これをより効率的に表現する方法を考えることはできません。

4
David

ファイルのリストがfilelist(1行に正確に1つのファイルパス)というファイルに保存され、圧縮ファイルをzipdirに保存するとすると、このbashスクリプトは次のようになります。望ましい結果:

_#!/bin/bash

while IFS= read file; do
    gzip -c "$file" > "zipdir/$(basename "$file").gz"
done < filelist
_

Bash/dashでは、上記をワンライナーに変換することもできます。

_while IFS= read file; do gzip -c "$file" > "zipdir/$(basename "$file").gz"; done < filelist
_

他のシェル(tcshやzshなど)

_bash -c 'while IFS= read file; do gzip -c "$file" > "zipdir/$(basename "$file").gz"; done < filelist'
_

仕事をします。

Bashが存在しない場合は、ダッシュに置き換えることができます。

使い方

  • _... < filelist_はfilelistの内容を_..._にリダイレクトします。

  • _while IFS= read file; do ... done_はファイルリストの行を調べ、現在処理されている行の内容を変数fileに格納し、_..._を実行します。

    _IFS=_は、内部ファイル区切り文字を変更します。これは、複数の先頭と末尾のスペースを適切に処理するために必要です。

  • gzip -c "$file" > "zipdir/$(basename "$file").gz"は、現在処理されているファイルを圧縮し、同じ名前に。gz拡張子を付けたファイルに出力を格納しますzipdir

    ここで、_basename "$file"_は、ファイルのパスからベアファイル名を抽出します。

5
Dennis

gzipがファイルからのパスの読み取りをサポートしているとは思いません。回避策は、すべてのターゲットファイルをアーカイブ(tar)に入れるか、それを数回実行することです。

ターゲットディレクトリが容量や転送速度に関して制限されていない場合、考えられる解決策は、 この回答 で概説されているように、ターゲットフォルダにファイルを圧縮する前にファイルを移動することです。

それ以外の場合は、一度に1つのファイル名を読み取り、フォルダーを圧縮して作成します。

フォルダ構造を作成します

TARGET=~/tmp/out

while read line; do 
    dirname "$line" ; 
done < list.txt | sort -u |
xargs -I%  echo mkdir -p "$TARGET/%"

  ## out: ##
  mkdir /home/jaroslav/tmp/out/code/bash 
  mkdir /home/jaroslav/tmp/out/recipes
  mkdir /home/jaroslav/tmp/out/samba
  mkdir /home/jaroslav/tmp/out/wikipedia

ファイルのコピー

while read line; do
   gzip -c "$SOURCE/$line" > "$TARGET/$line.gz"
done < list.txt

コマンド

  • dirname:ファイルパスの最後の部分を削除し、ディレクトリを残します
  • read [arg] <file:ファイルから一度に1行ずつ読み取り、シェル変数argに格納します。
  • sort -u:重複するエントリを削除します(uniqueのままにします)
  • xargs -I%:パイプからの要素(ディレクトリ名)ごとに1回コマンド(echo ....)を実行します(|)
  • gzip -c in> out:圧縮してstdoutに書き込みます(-c)。 > stdinをという名前のファイルにリダイレクトします。