web-dev-qa-db-ja.com

あるディレクトリから別のディレクトリにファイルをコピーする

あるフォルダーから別のフォルダーに一連のファイルをコピーする必要があり、次のコマンドを使用しています。

cp -rf `head -n 100 /home/tmp/abc.txt` /home/tmp/test/files

abc.txtのファイル内容は次のようになります。

./folder1/example.tar.gz
./folder2/example.tar.gz
./folder3/example.tar.gz

しかし、上記のcpコマンドを実行すると、次のようになります。

cp: will not overwrite just-created `/home/tmp/test/files/example.tar.gz' with `./folder3 /example.tar.gz'
cp: will not overwrite just-created `/home/tmp/test/files/example.tar.gz' with `./folder1/example.tar.gz'

.gzファイルの名前がエラーで表示されているものと同じであるため、理解できます。私がやりたいことは、/home/tmp/test/files内にabc.txtにリストされているのと同じフォルダー構造を持たせることです。

/home/tmp/test/files/folder1/example.tar.gz
/home/tmp/test/files/folder2/example.tar.gz
/home/tmp/test/files/folder3/example.tar.gz

しかし、上記のcpコマンドを実行した後、ファイルフォルダー内のexample.tar.gzが1つだけ取得されます。

それで、私が上で述べたものを得る方法は何ですか?

6
Mano

cpは機能しません

Copyはディレクトリ構造をコピーしないため、現状の例は機能しません。ファイルのみをコピーするため、発生するエラーメッセージが表示されます。このようなディープコピーを行うには、tarコマンドを入力して、コンストラクトtar cvf - --files-from=... | (cd /home/tmp/test/files/; tar xvf -)を使用するか、rsyncを使用します。

rsync

私があなただったら、rsyncを使って次のようにします。

$ rsync -avz --files-from=abc.txt /src /home/tmp/test/files/.

ファイルabc.txtの最初の100行だけが必要な場合は、次のようにします。

$ rsync -avz --files-from=<(head -n 100 abc.txt) /src /home/tmp/test/files/.

フォルダーデータの例:

$ tree /home/saml/tmp/folder*
/home/saml/tmp/folder1
`-- example.tar.gz
/home/saml/tmp/folder2
`-- example.tar.gz
/home/saml/tmp/folder3
`-- example.tar.gz

次に、ファイルをコピーします。

$ rsync -avz --files-from=<(head -n 3 /home/saml/tmp/abc.txt) \
         /home/saml/tmp/. /home/saml/tmp/test/files/.
building file list ... done
./
folder1/
folder1/example.tar.gz
folder2/
folder2/example.tar.gz
folder3/
folder3/example.tar.gz

sent 3147093 bytes  received 81 bytes  6294348.00 bytes/sec
total size is 3145728  speedup is 1.00

コピーされたことを確認します。

$ tree /home/saml/tmp/test/files
/home/saml/tmp/test/files
|-- folder1
|   `-- example.tar.gz
|-- folder2
|   `-- example.tar.gz
`-- folder3
    `-- example.tar.gz

tar

興味がある場合は、tarだけを使用してください。

$ cd /home/saml/tmp
$ tar cvf - --files-from=<(head -n 3 /home/saml/tmp/abc.txt) | (cd /home/saml/tmp/test/files/; tar xvf -)
./folder1/example.tar.gz
./folder1/example.tar.gz
./folder2/example.tar.gz
./folder2/example.tar.gz
./folder3/example.tar.gz
./folder3/example.tar.gz

コピーされたことを確認します。

$ tree /home/saml/tmp/test/files
/home/saml/tmp/test/files
|-- folder1
|   `-- example.tar.gz
|-- folder2
|   `-- example.tar.gz
`-- folder3
    `-- example.tar.gz
6
slm

問題は、cpがディレクトリ構造をコピーしないことではありません。もちろんそうです:cp -r(再帰的)。

cp、少なくともPOSIX cpが行わないことは、宛先オペランドにソースオペランドの相対パスを再作成することです。

cp a/b/file1 a/b/file2 a/c/file3 destの場合、dest/file1 dest/file2 dest/file3を取得します。

cpがGNU Coreutilsからのものである場合、--parentsオプションがある可能性があります。いつ導入されたかは不明です。cp --parentsは= GNU cpこのパスの再作成メカニズムを作成します。情報ドキュメントから:

--parents
  Form the name of each destination file by appending to the target
  directory a slash and the specified name of the source file.  The
  last argument given to `cp' must be the name of an existing
  directory.  For example, the command:

      cp --parents a/b/c existing_dir

  copies the file `a/b/c' to `existing_dir/a/b/c', creating any
  missing intermediate directories.

したがって、GNU cpがある場合、必要な唯一の変更は、-rを削除することです。これは、再帰的ではないためです。--parentsを使用します。

cp --parents -f `head -n 100 /home/tmp/abc.txt` /home/tmp/test/files
0
Kaz