ディレクトリツリー構造を複製し、特定の日以降に変更されたディレクトリにファイルをコピーします。

ディレクトリツリー構造を複製し、特定の日以降に変更されたディレクトリにファイルをコピーします。

30以上のサブディレクトリを持つフォルダがあり、指定された日付(たとえば9月8日、これが本当です)以降に変更されたファイルのリストを取得し、同じツリー構造を使用してコピーを作成したいと思います。そのファイルのみが変更されます。フォルダ内のファイル

私は30のディレクトリを話し、最後の変更日の検索ファイルのリストを使用してコマンド出力を見つけました。

a/a.txt
a/b/b.txt
a/www.txt
etc..

たとえば、「a」フォルダを作成し、その中にa.txtだけを含めたいと思います...同様に、他のフォルダに対しても「a / b」が作成され、その中にb.txtが含まれます...

答え1

テキストファイルに必要なファイルがあると仮定すると、次のことができます。

while IFS= read -r file; do 
    echo mkdir -p ${file%/*}; 
    cp /source/"$file" /target/${file%/*}/${file##*/}; 
done < files.txt 

その後、リストの各行を読み取り、ディレクトリとファイル名を抽出し、ディレクトリを作成し、ファイルをコピーします。sourceとをtarget使用している実際の親ディレクトリに変更する必要があります。たとえば、/foo/a/a.txtにコピーするには、 と に変更/bar/a/a.txtします。sourcefootargetbar


あなたの質問からコピーしたいかどうかわかりませんみんなディレクトリを選択し、特定のファイルのみを希望する場合、またはファイルを含むディレクトリのみを希望する場合。上記のソリューションは必要なディレクトリのみを生成します。これらすべてを生成するには、次のようにします。

find /source -type d -exec mkdir -p {} /target

これによりディレクトリが作成されます。これらのファイルが存在する場合は、ファイルをコピーするだけです。

while IFS= read -r file; do 
    cp /source/"$file" /target/"$file"
done

修正する

この小さなスクリプトは、9月8日以降に変更されたすべてのファイルを移動します。 .Linuxfindtouch使用すると仮定すると、これが可能です。

#!/usr/bin/env bash    

## Create a file to compare against.
tmp=$(mktemp)
touch -d "September 8" "$tmp"

## Define the source and target parent directories
source=/path/to/source
target=/path/to/target

## move to the source directory
cd "$source"

## Find the files that were modified more recently than $tmp and copy them
find ./ -type f -newer "$tmp" -printf "%h %p\0" | 
    while IFS= read -rd '' path file; do
        mkdir -p "$target"/"$path"
        cp "$file" "$target"/"$path"
    done

厳密に言えば、tmpファイルは必要ありません。ただし、これにより明日も同じスクリプトが機能します。それ以外の場合、find'sを使用すると、-mtime毎日正確な日付を計算する必要があります。


もう1つの方法は、まずディレクトリを見つけてターゲットに作成し、ファイルをコピーすることです。

  1. 作るみんな目次

     find ./ -type d -exec mkdir -p ../bar/{} \;
    
  2. 関連ファイルの検索とコピー

     find ./ -type f -newer "$tmp" -exec cp {} /path/to/target/bar/{} \;
    
  3. 空のディレクトリをすべて削除

     find ../bar/ -type d -exec rmdir {} \;
    

答え2

公園

公園仕事に最適なツールです。これはPOSIXをcpio置き換えますtartarそれとは異なり、アーカイブの作成と抽出だけでなく、パススルーモードも含まれます)。残念ながら、いくつかのLinuxディストリビューションのデフォルトインストールでは省略されていますが、apt-get// yum/ emerge...呼び出しだけです。

Paxには制限があります。最近変更されたディレクトリには、コピーするファイルが含まれていなくてもコピーされます。その後、空のディレクトリを削除できます(保持するターゲットに既存の空のディレクトリがない場合)。

cd /path/to/source
pax -rw -pp -T 201409080000 . /path/to/destination/
find /path/to/destination/ -depth -type d -exec rmdir {} +

paxフィルタなしで類似しているが同じではないユースケースに適用できる他の方法について説明します。

ジッシュ

使用グローバル予選 m変更時間ごとにファイルを一致させ(たとえば、m-10過去10日以内に変更されたファイルの代わりに別の単位を使用できます)、通常の.ファイルを一致させます。これ履歴修飾子 hファイル名のディレクトリ部分を保持します。

cd /path/to/source
for x in **/*(.m-10); do
  mkdir -p -- $x:h
  cp -p -- $x /path/to/destination/$x
done

または、次のものを使用できます。zmv関数はワイルドカード表現と一致するファイルをコピーします。ターゲットディレクトリを作成する組み込み方法がないため、これを行う関数を提供しました。

autoload -U zmv
mkdir_cp () {
  mkdir -p -- ${(P)#}:h
  cp -- $@
}
cd /path/to/source
zmv -p mkdir_cp -Q '**/*(.m-10)' '/path/to/destination/$f'

POSIX照会

Passを使用すると、過去10日以内に変更されたファイルを一致させることがfindできます。-mtime -10-newer reference_timereference_files

touch -t 201409080000 /tmp/reference_time
cd /path/to/source
find . -type f -newer /tmp/reference_time -exec sh -c '
  mkdir -p /path/to/destination/"${0%/*}"
  cp "$0" "/path/to/destination/$0"
' {} \;

答え3

findこれを行うには、withを使用できますrsync

find ./source/ -newer /tmp/foo -print0 | rsync -av --files-from=- --from0 ./ ./destination/ 

テスト

  1. 私は2つのディレクトリを作成しました。源泉そして目的地
  2. テスト目的で、以下のようにタイムスタンプを含む一時ファイルを作成しました。

    touch --date "2014-09-08" /tmp/foo
    
  3. 今内部源泉ディレクトリにコピーする必要があるいくつかのサブディレクトリを作成しました。目的地ディレクトリ(一部のサブディレクトリにはテスト目的のためにスペースがあります)もいくつかのサンプルファイルを作成しました。これ 目的地ディレクトリは現在空です。

  4. サブディレクトリにあるファイルの1つの作成日を変更しました。

    touch -c -t 1110111730 oldfile
    
  5. 次にfind、指定されたとおりにコマンドを実行します。このfind コマンドは、指定した基準に従ってすべてのファイルを検索し、コマンドで生成されたファイルのリストをパイプしますrsyncfind

目的地ディレクトリに指定されたファイルがoldfile私たちが望むよりも速いので、そこにはいけません。

そのため、ディレクトリに移動してdestination目的のサブディレクトリ構造と検索基準に一致するすべてのファイルを取得しましたが、指定されたファイルはoldfile存在しません。

引用する

http://www.commandlinefu.com/commands/view/1481/rsync-find

答え4

これがまさにcpioデザインが使われる方法です。

find . -whatever -print | cpio -pvmd /path/to/copy/to/.

完璧。

関連情報