44

UNIX bash シェル (具体的には Mac OS X Leopard) で、特定の拡張子を持つすべてのファイルをフォルダー階層 (サブディレクトリを含む) から同じ宛先フォルダー (サブフォルダーなし) にコピーする最も簡単な方法は何でしょうか?

明らかに、ソース階層に重複があるという問題があります。それらが上書きされてもかまいません。

例: 次の階層のすべての .txt ファイルをコピーする必要があります

/foo/a.txt
/foo/x.jpg
/foo/bar/a.txt
/foo/bar/c.jpg
/foo/bar/b.txt

「dest」という名前のフォルダーに移動して、次を取得します。

/dest/a.txt
/dest/b.txt
4

5 に答える 5

61

バッシュで:

find /foo -iname '*.txt' -exec cp \{\} /dest/ \;

find大文字と小文字を区別せず/fooに、ワイルドカードに一致するパスの下にあるすべてのファイルを検索します(これが意味します)。ファイルごとにが実行され、見つかったファイルが の代わりに使用されます。*.txt-inamefindcp {} /dest/{}

于 2008-08-26T09:26:18.137 に答える
14

Magnus のソリューションの唯一の問題は、すべてのファイルに対して新しい「cp」プロセスをフォークすることです。これは、特に多数のファイルがある場合、非常に効率的ではありません。

Linux (または GNU coreutils を使用する他のシステム) では、次のことができます。

find . -name "*.xml" -print0 | xargs -0 echo cp -t a

( -0 を指定すると、ファイル名にスペースなどの奇妙な文字が含まれている場合に機能します。)

残念ながら、Mac には BSD スタイルのツールが付属していると思います。「-t」スイッチに相当する「標準」を知っている人はいますか?

于 2008-08-26T11:02:36.717 に答える
12

上記の回答では、ファイルが上書きされることを質問者が気にしないため、名前の衝突は許可されていません。

ファイルが上書きされるのは気になりますので、別のアプローチを考え出しました。パス内の各/を-に置き換えると、名前の階層が維持され、すべてのファイルが1つのフラットフォルダーに配置されます。

findを使用してすべてのファイルのリストを取得し、awkを使用して元のファイル名と変更されたファイル名を使用してmvコマンドを作成し、それらをbashに渡して実行します。

find ./from -type f | awk '{ str=$0; sub(/\.\//, "", str); gsub(/\//, "-", str); print "mv " $0 " ./to/" str }' | bash

ここで、。/fromおよび./toは、mvfromおよびtoへのディレクトリです。

于 2010-07-12T12:18:08.917 に答える
3

本当に 1 つのコマンドだけを実行したい場合は、1 つのコマンドを実行して実行してみませんか? そのようです:

$ find /foo  -name '*.txt' | xargs echo | sed -e 's/^/cp /' -e 's|$| /dest|' | bash -sx

ただし、これを頻繁に行うか、大量のファイルを持っていない限り、パフォーマンスに関してはそれほど重要ではありません。ただし、名前の共謀には注意してください。テストで、GNU cp が少なくとも衝突を警告することに気付きました。

cp: will not overwrite just-created `/dest/tubguide.tex' with `./texmf/tex/plain/tugboat/tubguide.tex'

私は最もきれいだと思います:

$ find /foo  -name '*.txt' | xargs -i cp {} /dest

-exec オプションより覚える構文が少ない。

于 2008-09-12T09:07:57.163 に答える
1

FreeBSD ボックスの cp のマニュアル ページに関する限り、-t スイッチは必要ありません。cp は、2 つ以上の名前が渡された場合、コマンド ラインの最後の引数がターゲット ディレクトリであると想定します。

于 2008-09-12T08:44:06.160 に答える