ファイルのリストをコピー


35

ファイル内にスペースで区切られたファイルのリストがありますlist.txt。それらを新しいフォルダにコピーしたいと思います。

私がやろうとしました:

cp `cat list.txt` new_folder

しかし、うまくいきませんでした。

どうしますか?

更新:

非常に興味深い回答をありがとうございます。私はそれほど多くを求めませんでした:)

上記の解決策を2回以上試した後cp、フォルダーnew_folderがまだ存在しなかったため、使用方法のヘルプが印刷されたようです!申し訳ありませんが、それはばかげた間違いのようです...以前にフォルダを作成すると、機能します。

しかし、私はあなたのすべての答えと解決策から多くを学びました。それらを書くのに時間を割いてくれてありがとう。


ひとつだけはっきりさせておきましょう。リストには、スペースのみで区切られたすべてのファイル名が1行に含まれていますか?または、名前はそれぞれ別の行にありますか?
テレマコス

スペースで区切られた1つのライム。ダグの解決策は働いた:)答えてくれてありがとう。
クラウス

それは面白いです...私は、各名前が別々の行にある行でソリューションをテストしました。
ダグ・ハリス

「機能しませんでした」はあまり意味がありません。正確にどのように機能しませんでした。それは私のためにうまく機能します。
追って通知があるまで一時停止します。

申し訳ありません:cpの使用法のヘルプが表示されました。上記の私の更新を参照してください。
クラウス

回答:


34

xargsを使用してみてください。

cat list.txt | xargs -J % cp % new_folder

更新:

GNU / Linuxバージョンとは異なるバージョンのOS Xでこれを行いました。xargs来ているのGNUのfindutilsはありません-Jが、それは持っている-I(デニスウィリアムソンは、コメントで指摘したように)似ています。OS Xバージョンのxargsには両方が-Iあり、-J動作がわずかに異なります。どちらもこの元の質問で機能します。

$ cat list.txt
one
two.txt
three.rtf

$ cat list.txt | xargs -J % echo cp % new_folder
cp one two.txt three.rtf new_folder

$ cat list.txt | xargs -I % echo cp % new_folder
cp one new_folder
cp two.txt new_folder
cp three.rtf new_folder

3
xargsはそれを持っ-Jていないが、それは-I同じことをするようだ。使用しているバージョンxargsとOS /ディストリビューションは何ですか?
追って通知があるまで一時停止します。

私はこれをMac OS X 10.6(別名ユキヒョウ)でテストしたので、OSに同梱されているxargsのどのバージョンでもあります。実行xargs --versionすると、使用法エラーメッセージが返されます。xargsのBSDバージョンである可能性があります。使用-Iとは-J微妙に異なっています。適切にフォーマットされた例で回答を更新します。
ダグ・ハリス

うん、私はMac OSX 10.6で作業しています。-J-I:) についての精度をありがとう
クラウス

コマンドを実行する前にエコーを使用してコマンドを確認することをお勧めします。
リアム

1
上記の同じコマンドを必要な変更のみで使用して、ファイルをコピーし、ディレクトリとサブディレクトリを作成し、スラッシュで区切るにはどうすればよいですか?
ヴィッキーDev

54

catまったく必要ありません:

xargs -a list.txt cp -t new_folder

または、長いオプションを使用します。

xargs --arg-file=list.txt cp --target-directory=new_folder

いくつかのシェルバージョンを以下に示します。forOPがファイル名をスペースで区切ることを指定したため、一部の変数が引用符で囲まれていないか、ループが特に使用されていることに注意してください。これらの手法の一部は、ファイル名に空白が含まれる行ごとのファイル名入力では機能しません。

バッシュ:

for file in $(<list.txt); do cp "$file" new_folder; done

または

cp $(<list.txt) new_folder

sh(またはBash):

# still no cat!
while read -r line; do for file in $line; do cp "$file" new_folder; done; done < list.txt

または

# none here either
while read -r line; do cp $line new_folder; done < list.txt

または

# meow
for file in $(cat list.txt); do cp "$file" new_folder; done

または

# meow
cp $(cat list.txt) new_folder

noobの質問:なぜ-t必要なのxargs -a list.txt cp -t new_folderですか?
i博ヤン

1
@YiboYang:はの-tオプションですcp。すべてのソース引数を指定されたターゲットディレクトリにコピーします。ここでは、xargsコマンドによって追加されるソースの前にターゲットを指定できます。
追って通知があるまで一時停止します。

これは便利ですが、list.txtにファイルとフォルダーのパスが混在している場合はどうなりますか?その場合、コマンドは正しく機能しません。「ディレクトリを省略しています...」と報告され、cpコマンドに-Rが指定されている場合、リスト内の最初のファイルが検出されるとすぐに「ディレクトリではない」エラーが報告されます。
ベミペフェ

7

私は以前ここで恥ずかしいほどラウンドアラウンドな回答をしていましたが、デニスの回答は私が最も基本的なものを見逃したことを思い出させました。そこで、元の回答を削除しました。しかし、この非常に基本的なことを誰も言っていないので、ここに置く価値があると思います。

元の質問は、「スペースで区切られたファイル名のリストを含むテキストファイルがあります。それらを1つのターゲットディレクトリにコピーするにはどうすればよいですか」です。どういうわけか、特定の方法でファイルからアイテムを抽出する必要があると思うので、これは最初は難しいか複雑に見えるかもしれません。ただし、シェルがコマンドラインを処理するとき、最初に行うことは、引数リストをトークンに分離し、(ここでは誰も明言していないビットが)トークンを分離します。(改行もトークンを分離するため、改行で区切られたリストを使用したダグ・ハリスのテストは同じ結果になりました。)つまり、シェルはスペースで区切られたリストを予期し、すでに処理できます。

したがって、ここで行う必要があるのは、スペースで区切られたリスト(既に持っているもの)をコマンドの適切な場所に置くことだけです。あなたのコマンドはこれに関するいくつかのバリエーションです:

cp file1 file2 file3...file# target

唯一の欠点は、テキストファイルからファイル1〜#のリストを取得することです。

Dennisがコメントで指摘しているように、元の試み(cpcat list.txt new_folder)はすでに機能しているはずです。どうして?内部コマンドcat list.txtは最初にシェルによって処理され、に展開されるためfile1 file2 file3...file#、これはシェルがコマンドのその部分で期待し、望んでいることとまったく同じです。うまくいかなかった場合は、(1)入力ミスがあるか、(2)ファイル名が何らかの形で奇妙でした(スペースまたはその他の異常な文字がありました)。

Dennisのすべての回答が機能する理由は、作業するために必要なファイルのリストを提供し、cpコマンド全体でそのリストをそのリストに配置するためです。繰り返しますが、コマンド自体の構造は次のとおりです。

cp list-of-files target_directory

このバージョンでは、これらすべてがどのように組み合わされるかを簡単に確認できます。

cp $(<list.txt) new_folder

$()これにより、シェルは括弧内のコマンドを実行し、大きな行のそのポイントで出力を置き換えます。次に、シェルは行全体を実行します。ちなみに、$()あなたはすでにバックティックス( `)で行っていたことのより新しいバージョンです。次<は、ファイルのリダイレクト演算子です。シェルに内容list.txtを標準入力にダンプするよう指示します。$()ビットが最初に処理されるため、段階的に次のようになります。

  1. cp $(<list.txt) new_folder # split line into three tokens: cp, $(<list.txt), new_folder
  2. cp file1 file2 file3...file# new_folder # substitute result of $(<list.txt) into the larger command

明らかに、ステップ2は単にcp必要な通常のコマンドです。

私はこの(おそらく非常に死んだ)馬をたくさんlotっていることに気づきましたが、やりがいがあると思います。シェルがコマンドを処理する方法を正確に理解することは、コマンドをより適切に記述し、大幅に簡素化するのに役立ちます。また、問題が隠れている可能性が高い場所も示します。この場合、たとえば、私の最初の質問は、おかしなファイル名や入力ミスの可能性についてでした。アクロバットは必要ありませんでした。


@Klausどういたしまして。率直に言って、私はデニスの答えを読んで、私が問題の重要な部分を完全に見逃していることに気づいた後、ほとんど自分自身に腹を立てました。あなたが好きな解決策もそこからです。
テレマコス

これは非常に古い答えですが、フォルダ構造を再作成する必要がある場合は、--parentsフラグが必要です。-vコピーされたものの記録のためにそれを冗長にすることができます。アクセス許可を保持する場合は、-aor -pフラグが必要です。すなわち、cp --parents -av $(<list.txt) new_folder。これはすべて、ファイルのリストが実際にはすべてのファイルであると想定しています。それ以外の場合は、-rフラグも再帰する必要があります。
ドーピン

@dhaupin実際、OPは彼がmacOSにいたと述べています。そのため、価値があるものとしては、--parentsフラグはそこに存在しません。(BSD派生)バージョンcpは短いオプションのみを提供し、GNUスタイルの長いオプションは提供しません。BSDスタイルのcp場合、再帰コピーのフラグは小文字-Rではなく大文字です。
テレマコス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.