複数のディレクトリ(その名前がリストに表示されている場合)のファイルを単一のディレクトリにコピーします。

複数のディレクトリ(その名前がリストに表示されている場合)のファイルを単一のディレクトリにコピーします。

私は巨大なフォルダツリーを持っており、各フォルダには約3レベル以下のいくつかのサブディレクトリがあります。以下は、レベルが1つしかない例です。

$ tree
.
|-- AB.txt
|-- CD.txt
|-- destination_folder
|-- spreadsheet.txt
`-- subdirectory
    `-- EF.txt

2 directories, 4 files

以下の興味のあるファイル名のリストがありますspreadsheet.txt

$ cat spreadsheet.txt 
AB.txt
CD.txt
EF.txt

spreadsheet.txtフォルダに表示されるすべてのファイルをコピーしたいですdestination_folder。助けてくれてありがとう!私はこれが関係すると思いましたが、findそれをcp理解することはできないようです。

ベストアンサー1

findファイル名に改行文字が含まれていないとし、ファイル名ごとに1回実行します。

#!/bin/sh

mkdir -p destination_folder || exit 1
while IFS= read -r name; do
    find . -path ./destination_folder -prune -o \
        -type f -name "$name" -exec cp {} destination_folder \;
done <spreadsheet.txt

まず、現在のディレクトリ内にターゲットディレクトリを作成します(または失敗すると終了します)。次に、入力ファイルを 1 行ずつ読み込み、呼び出して、findその名前の一般ファイルを探します。検索でターゲットディレクトリが見つかるたびに、次を使用して明示的findにこれを回避します。-prune

正しい名前のファイルが見つかると、そのファイルがターゲットディレクトリにコピーされます。複数のファイルの名前が同じ場合はコピーをdestination_folder上書きします。

現在のディレクトリが大きい場合、またはファイル名のリストが長い場合(ただし数千行ではない)、作業が遅くなります。だから私たちは一つ私たちに電話してくださいfind。以下のコードはbash配列を使用しているため、たとえば実行されているとします。

#!/bin/bash

mkdir -p destination_folder || exit 1

names=()
while IFS= read -r name; do
    names+=( -o -name "$name" )
done <spreadsheet.txt

find . -path ./destination_folder -prune -o \
    \( "${names[@]:1}" \) -type f -exec cp -t destination_folder {} +

ここでは、見つかったファイルごとに1回ではなく、できるだけ少ない数の呼び出しを実行するためにcp -t(GNUcp拡張)を使用することにしました。cp

上記のコードはnames最終的にfind。あなたの質問の例によれば、上記のコードの最後で実行される実際のコマンドは次のようになります。

find . -path ./destination_folder -prune -o '(' -name AB.txt -o -name CD.txt -o -name EF.txt ')' -type f -exec cp -t destination_folder '{}' +

ターゲットディレクトリ内のファイル名の競合の問題を回避するには、GNUを使用する場合(Linuxシステムなど)またはオプションをcp使用してください。cp-b--backup

Linux以外のシステムでは、通常、cpパッケージマネージャを介してGNU coreutilsをインストールした後にGNUを使用できます。gcp


最後のスクリプト/bin/sh(無制限の配列):

#!/bin/sh

mkdir -p destination_folder || exit 1

set --
while IFS= read -r name; do
    set -- -o -name "$name" "$@"
done <spreadsheet.txt

shift

find . -path ./destination_folder -prune -o \
    \( "$@" \) -type f -exec cp -t destination_folder {} +

おすすめ記事