サブディレクトリ「Movie Name」を含む「Movies」ディレクトリがあります。各サブディレクトリ「映画名」には、映画ファイル、関連する画像/情報ファイルなどが含まれています。
「.avi」タイプのムービーファイルを含むすべてのディレクトリを外部USBデバイスにコピーしようとしています。
したがって、Directory/subdirectory A
と が含まれている場合は、そのディレクトリとその内容を外部ドライブにコピーしたいと思います。movie.avi
poster.jpg
movie.nfo
私はこれを試しました:
find . -name "*.avi" -printf "%h\n" -exec cp {} /share/USBDisk1/Movies/ \;
ただし、ディレクトリとファイルの内容ではなくファイルのみをコピーします。
ベストアンサー1
まず、試みが機能しない理由:-printf "%h\n"
filenameのディレクトリ部分を印刷してください.avi
。これは-exec
後続の操作には影響しません。{}
「最後に印刷されたコマンド」を意味するのではなく、printf
「検出されたファイルへのパス」を意味します。
コマンドでファイル名のディレクトリ部分を使用するには、cp
ファイル名を渡す必要がありますcp
。find
コマンドにはこの機能はありませんが、シェルにはあるので、 make がfind
呼び出すシェルを呼び出しますcp
。
find . -name "*.avi" -exec sh -c 'cp -Rp "${0%/*}" /share/USBDisk1/Movies/' {} \;
ディレクトリをコピーするので-r
、 。.cp
-p
cp -Rp
この方法では、rsync -a
ムービーディレクトリをすでにコピーしている場合は、内容が変更されない限り再コピーされません。
あなたのコマンドには、あなたに影響を与える可能性があり、そうでない可能性がある欠陥があります。ディレクトリに複数の.avi
ファイルが含まれている場合は、複数回コピーされます。ファイルを.avi
見つけるよりもディレクトリを見つけてファイルが含まれている場合は、コピーすることをお勧めします.avi
。rsync
代わりに、ファイルは再コピーされず、ファイルの存在を確認し続けるためにcp
さらに多くの作業が必要になります。rsync
すべてのムービーディレクトリが最上位ディレクトリのすぐ下にある場合、これは必要ではなく、find
ワイルドカードパターンの単純なループで十分です。
for d in ./*/; do
set -- "$d/"*.avi
if [ -e "$1" ]; then
# there is at least one .avi file in $d
cp -rp -- "$d" /share/USBDisk1/Movies/
fi
done
ムービーディレクトリがネストされている場合(たとえばMovies/science fiction/Ridley Scott/Blade Runner
、)これは必要ではなく、find
ワイルドカードパターンの単純なループで十分です。 ksh93またはbash≥4またはzshを実行し、ksh93では最初に実行し、bashでは最初に実行する必要がありset -o globstar
ます。shopt -s globstar
ワイルドカードパターンは、**/
現在のディレクトリとすべてのサブディレクトリを繰り返し一致させます(bashはサブディレクトリへのシンボリックリンクも通過します)。
for d in ./**/; do
set -- "$d/"*.avi
if [ -e "$1" ]; then
cp -rp -- "$d" /share/USBDisk1/Movies/
fi
done