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
します。source
foo
target
bar
あなたの質問からコピーしたいかどうかわかりませんみんなディレクトリを選択し、特定のファイルのみを希望する場合、またはファイルを含むディレクトリのみを希望する場合。上記のソリューションは必要なディレクトリのみを生成します。これらすべてを生成するには、次のようにします。
find /source -type d -exec mkdir -p {} /target
これによりディレクトリが作成されます。これらのファイルが存在する場合は、ファイルをコピーするだけです。
while IFS= read -r file; do
cp /source/"$file" /target/"$file"
done
修正する
この小さなスクリプトは、9月8日以降に変更されたすべてのファイルを移動します。 .Linuxfind
をtouch
使用すると仮定すると、これが可能です。
#!/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つの方法は、まずディレクトリを見つけてターゲットに作成し、ファイルをコピーすることです。
作るみんな目次
find ./ -type d -exec mkdir -p ../bar/{} \;
関連ファイルの検索とコピー
find ./ -type f -newer "$tmp" -exec cp {} /path/to/target/bar/{} \;
空のディレクトリをすべて削除
find ../bar/ -type d -exec rmdir {} \;
答え2
公園
公園仕事に最適なツールです。これはPOSIXをcpio
置き換えますtar
(tar
それとは異なり、アーカイブの作成と抽出だけでなく、パススルーモードも含まれます)。残念ながら、いくつかの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_time
reference_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/
テスト
- 私は2つのディレクトリを作成しました。源泉そして目的地。
テスト目的で、以下のようにタイムスタンプを含む一時ファイルを作成しました。
touch --date "2014-09-08" /tmp/foo
今内部源泉ディレクトリにコピーする必要があるいくつかのサブディレクトリを作成しました。目的地ディレクトリ(一部のサブディレクトリにはテスト目的のためにスペースがあります)もいくつかのサンプルファイルを作成しました。これ 目的地ディレクトリは現在空です。
サブディレクトリにあるファイルの1つの作成日を変更しました。
touch -c -t 1110111730 oldfile
次に
find
、指定されたとおりにコマンドを実行します。このfind
コマンドは、指定した基準に従ってすべてのファイルを検索し、コマンドで生成されたファイルのリストをパイプしますrsync
。find
今目的地ディレクトリに指定されたファイルがoldfile
私たちが望むよりも速いので、そこにはいけません。
そのため、ディレクトリに移動してdestination
目的のサブディレクトリ構造と検索基準に一致するすべてのファイルを取得しましたが、指定されたファイルはoldfile
存在しません。
引用する
答え4
これがまさにcpio
デザインが使われる方法です。
find . -whatever -print | cpio -pvmd /path/to/copy/to/.
完璧。