定義されている古いファイルをソースディレクトリから宛先ディレクトリに移動する次のスクリプトを作成しました。完全に機能しています。
#!/bin/bash
echo "Enter Your Source Directory"
read soure
echo "Enter Your Destination Directory"
read destination
echo "Enter Days"
read days
find "$soure" -type f -mtime "-$days" -exec mv {} "$destination" \;
echo "Files which were $days Days old moved from $soure to $destination"
このスクリプトはファイルを移動します。また、ソースサブディレクトリのファイルも移動しますが、サブディレクトリを宛先ディレクトリに作成しません。この追加機能を実装したい。
例で
/home/ketan : source directory
/home/ketan/hex : source subdirectory
/home/maxi : destination directory
このスクリプトを実行すると、hexのファイルもmaxiディレクトリに移動しますが、同じhexをmaxiディレクトリに作成し、そのファイルを同じhexに移動する必要があります。
mv /home/ketan/hex/foo /home/maxi
を実行する代わりに、find
によって生成されたパスに基づいてターゲットディレクトリを変更する必要があります。これは、最初にソースディレクトリに移動してfind .
を実行すると簡単です。これで、find
によって生成された各アイテムの宛先ディレクトリを単に追加できます。 find … -exec
コマンドでシェルを実行して連結を実行し、必要に応じてターゲットディレクトリを作成する必要があります。
destination=$(cd -- "$destination" && pwd) # make it an absolute path
cd -- "$source" &&
find . -type f -mtime "-$days" -exec sh -c '
mkdir -p "$0/${1%/*}"
mv "$1" "$0/$1"
' "$destination" {} \;
$destination
に特殊文字が含まれている場合に、引用の問題を回避するために、シェルスクリプト内でそれを置き換えることはできません。それを環境にエクスポートして内部シェルに到達させるか、または引数として渡すことができます(それが私が行ったことです)。 sh
呼び出しをグループ化することで、実行時間を少し節約できます。
destination=$(cd -- "$destination" && pwd) # make it an absolute path
cd -- "$source" &&
find . -type f -mtime "-$days" -exec sh -c '
for x do
mkdir -p "$0/${x%/*}"
mv "$x" "$0/$x"
done
' "$destination" {} +
または、zshでは、 zmv
function を使用し、.
およびm
glob qualifiers を使用してのみ一致させることができます正しい日付範囲の通常のファイル。必要に応じて、最初にターゲットディレクトリを作成する代替のmv
関数を渡す必要があります。
autoload -U zmv
mkdir_mv () {
mkdir -p -- $3:h
mv -- $2 $3
}
zmv -Qw -p mkdir_mv $source/'**/*(.m-'$days')' '$destination/$1$2'
find
が指定されたことは知っていますが、これはrsync
の仕事のように思えます。
私は最もよく以下を使用します:
rsync -axuv --delete-after --progress Source/ Target/
特定のファイルタイプ( example )のファイルのみを移動する場合の良い例を次に示します。
rsync -rv --include '*/' --include '*.js' --exclude '*' --Prune-empty-dirs Source/ Target/
それは効率的ではありませんが、私の意見では、ファイルをコピーして後で削除するだけであれば、コードは読みやすく、理解しやすくなります。
find /original/file/path/* -mtime +7 -exec cp {} /new/file/path/ \;
find /original/file/path/* -mtime +7 -exec rm -rf {} \;
通知:自動操作のために@MVによって発見された欠陥:
2つの別々の操作を使用するのは危険です。コピー操作の実行中に7日以上経過した一部のファイルはコピーされませんが、削除操作によって削除されます。これは問題ではないかもしれませんが、手動で行われている場合は自動化されたスクリプトの場合、データが失われる可能性があります
find(1)の2つのインスタンスを使用してそれを行うことができます
常にcpio(1)があります
(cd "$soure" && find … | cpio -pdVmu "$destination")
Cpioの引数を確認してください。私があげたもの
これを行うには、find
によって返されたファイルの絶対パスを宛先パスに追加します。
find "$soure" -type f -mtime "-$days" -print0 | xargs -0 -I {} sh -c '
file="{}"
destination="'"$destination"'"
mkdir -p "$destination/${file%/*}"
mv "$file" "$destination/$file"'
また、ファイル名に特殊文字が含まれている場合、ファイル名の影響を受けません(移動ではなくコピーを実行することにより、最も速く、ストレージ領域を消費しません)。
export destination
find "$soure" -type f "-$days" -print0 | xargs -0 -n 10 bash -c '
for file in "$@"; do
echo -n "Moving $file to $destination/"`dirname "$file"`" ... "
mkdir -p "$destination"/`dirname "$file"`
\mv -f "$file" "$destination"/`dirname "$file"`/ || echo " fail !" && echo "done."
done'
または、「並列」コマンドを使用して、マルチCPUで多数のファイルを同時に移動します。
echo "Move oldest $days files from $soure to $destination in parallel (each 10 files by "`parallel --number-of-cores`" jobs):"
function move_files {
for file in "$@"; do
echo -n "Moving $file to $destination/"`dirname "$file"`" ... "
mkdir -p "$destination"/`dirname "$file"`
\mv -f "$file" "$destination"/`dirname "$file"`/ || echo " fail !" && echo "done."
done
}
export -f move_files
export destination
find "$soure" -type f "-$days" -print0 | parallel -0 -n 10 move_files
PS:タイプミスがあります。「酸味」は「ソース」である必要があります。変数名はそのままにしておきました。
これに対する本当に簡単な解決策はないようで、私はそれを頻繁に必要とするので、私はLinux用のこのオープンソースユーティリティを作成しました(Pythonが必要です): https://github.com/benapetr/smv
それを使用して必要なものを達成する方法はいくつかありますが、おそらく最も簡単な方法は次のようになります。
# -vf = verbose + force (doesn't stop on errors)
smv -vf `find some_folder -type f -mtime "-$days"` target_folder
さらに、それをドライモードで実行して、何もしないで何をするかを印刷することができます
smv -rvf `find some_folder -type f -mtime "-$days"` target_folder
または、ファイルのリストが長すぎて引数行に収まらない場合、pythonをすべてのファイルに対して実行してもかまいません。
find "$soure" -type f -mtime "-$days" -exec smv {} "$destination" \;
これはエレガントではありませんが、ファイルの数/サイズがあまり大きくない場合は簡単です
ファイルをZip
アーカイブに圧縮してから、-j
オプションなしで宛先で解凍します。デフォルトでは、Zipは相対ディレクトリ構造を作成します。
この方法を試してください:
IFS=$'\n'
for f in `find "$soure" -type f -mtime "-$days"`;
do
mkdir -p "$destination"/`dirname $f`;
mv $f "$destination"/`dirname $f`;
done