複数のファイルをワイルドカードでコピーするにはどうすればよいですか?


42

ABC。*に多数のファイルを含むフォルダーがあります(このようなファイルは約100個あります)。それらをすべてDEF。*で始まる名前の新しいファイルに複製したい

だから、私は欲しい

ABC.Page1
ABC.Page2
ABC.Topic12
...etc

にコピーされました

DEF.Page1
DEF.Page2
DEF.Topic12
...etc

バッチコマンド(BASHなど)でこれを行う最も簡単な方法は何ですか?私はsed、awk、またはxargsを含むものを考えていますが、構文を理解するのが困難です。Pythonスクリプトを書くことはできますが、おそらくあまり複雑ではないコマンドラインソリューションがあると考えています。


由緒あるmcファイルマネージャーは、この種の一括名前変更を最も広範囲にサポートしています。
oakad 14

@oakad tarも春鶏ではありません。例については私の答えをご覧ください。
mikeserv 14

回答:


41

bashでこのようなものはどうですか:

for file in ABC.*; do cp "$file" "${file/ABC/DEF}";done

cpコマンドの前にechoを置くことでテストできます:

for file in ABC.*; do echo cp "$file" "${file/ABC/DEF}";done

完璧です。私が想像したよりも簡単です。
タコ14

ほとんどの場合これで十分ですが、ここではエコーを確認することが重要です。スクリプトでこれを実行しないでください。詳細情報は、読みのために、bashの落とし穴
pawel7318を

@ pawel7318、あなたが与えたリンクは、優れたアドバイスではありますが、上記のコマンドには当てはまらないようです。私は、このコマンドで参照のみのエッジケースがあります:(1)は、対象ファイルがすでに存在するかどうかを確認しないでもターゲットファイルが既にとして存在する場合は、ディレクトリ(ファイルをコピーすることになる現在の名前を保持し、ディレクトリ)、 (2)glob展開が単一のコマンドラインに収まらないほど多くのファイルがある場合。
ワイルドカード

1
私はこれを得る:cp /usr/local/lib/libboost* /usr/local/lib/libboost*エコーチェックで。
トマーシュザト

8

多数のファイルでこれを効率的に行うには、ファイルcpごとに異なるプロセスを開始しないようにすることをお勧めします。1つの方法は、コピーしてから名前を変更することですprenamerenameDebianベースのディストリビューションではデフォルトでこれにシンボリックリンクされています)。これとLinuxの使用mktemp

tmp=$(mktemp -d --tmpdir=.)
cp ABC.* "$tmp"
prename "s:$tmp/ABC:DEF:" "$tmp/"*
rmdir "$tmp"

更新

実際paxにここに行くより良い方法かもしれません:

pax -rws '/^ABC/DEF/' ABC.* .

残念ながら、paxPOSIXとLinux Standard Baseの両方であるにもかかわらず、現在デフォルトで含まれているディストリビューションはほとんどありません。


エスケープを回避するための区切り文字として:を使用する良いタッチ。
クレイトンスタンレー14

5

tar 本当に速くあなたのためにこれを行います。

テスト

まず、2つのディレクトリと10個のファイルを作成しました。

% mkdir test1 test2 ; cd test1
% for n in `seq 1 10` ; do touch ABC.file$n ; done
% ls

> ABC.file1   ABC.file2  ABC.file4  ABC.file6  ABC.file8
> ABC.file10  ABC.file3  ABC.file5  ABC.file7  ABC.file9

それから私はそれらをコピーしました:

% tar -cf - ./* |\ 
    tar -C../test2 --transform='s/ABC/DEF/' -xf -
% ls ../test2

> DEF.file1   DEF.file2  DEF.file4  DEF.file6  DEF.file8
> DEF.file10  DEF.file3  DEF.file5  DEF.file7  DEF.file9

変換

したがって、GNU tarsed --transform=EXPRESSIONファイル名の変更を受け入れます。これにより、一部のファイルの名前だけを変更することもできます。例えば:

% tar -cf - ./* |\ 
    tar -C../test2 --transform='s/ABC\(.*[0-5]\)/DEF\1/' -xf -
% ls ../test2

> ABC.file6  ABC.file8  DEF.file1   DEF.file2  DEF.file4
> ABC.file7  ABC.file9  DEF.file10  DEF.file3  DEF.file5

それが一つの利点です。

ストリーム

また、これは2つのtarプロセスのみであり、ファイル数に関係なく変更されないことを考慮してください。

tar | tar

tarあなたが望むように最適化されています。これにより、問題のある引数カウントや子プロセスの暴走が発生することはありません。これは、A> B完了です。

引数

tarここでは、2つのプロセス間で組み合わせた7つの異なる引数を使用します。最も重要なものを最初にここにリストします。

-stdout / stdin-これは、アーカイブを構築または抽出しているかどうかに応じてtar、入力または出力をストリーミングすることを通知しstdin/stdoutます。

-ccreate-tarアーカイブを構築するよう指示します。tar期待される次の引数は...

-fファイル - テープデバイスなどではなくtarfileオブジェクトで動作することを指定します。そして、上で述べたように、それが動作するファイルはstdin/stdout-つまり、私たちの|pipe

./*すべての$ PWD / files-アーカイブ引数が最初に来ることを除いて、ここでは説明しすぎないよう-にし./*ます。

...そしてその反対側に|pipe...

-Cディレクトリの変更 -これはtar、他のアクションを実行する前に指定したディレクトリに変更する必要があることを通知するため、cd ../test2抽出の直前に効果的に実行します。

--transform='s/ed/EXPR/'-すでに述べたように、これは名前を変更しました。しかし、ドキュメントでは、任意のsed式またはを使用できることが示されています//flag

-x抽出 - tarターゲットディレクトリを変更し、名前の変更指示を受け取った後、-f - |pipeアーカイブファイルから現在のディレクトリにすべてのファイルの抽出を開始するよう指示します。ミステリーはありません。


1
ここでpax、この質問のためのソリューション。私は答えにそれを追加しますが、私はそれがここでより適していると思うpax -rws '/^ABC/DEF/' ABC.* .
グレアム14

@Graeme-うわー-それはずっと良いです!男は、真珠の名前を変更することで地獄を打ち負かします!これを答えに入れる必要がありますpax-POSIXが指定されているため- paxです。
mikeserv 14

paxPOSIXかもしれませんが、残念ながらデフォルトでインストールされることはめったにありません。
グレアム14

4

あまり標準的でないツールを使用しても構わないのであれば、この種のタスクのために書かれたmmv(mass move)を使用することをお勧めします。mcpスイートの一部である(一括コピー)を使用すると、簡単にできます

mcp "ABC.*" "DEF.#1"

ダウンロードパッケージを見つけるのは簡単ではありません。自宅でコンパイルするための現在のDebianパッケージ(ArchもAURで使用しています)は、ここにあります


すぐにubuntu 15.10にインストールしますapt-get install mmv
Thufir

2

zshで、次の行をに追加します.zshrc

autoload -U zmv
alias zmv='noglob zmv'
alias zcp='zmv -C'
alias zln='zmv -L'

次に、コマンドラインで、次を実行できます。

zcp 'ABC(.*)' 'DEF$1'

または単に

zcp -W ABC.* DEF.*

別のシェルで、zshがインストールされている限り:

zsh -c 'autoload zmv; noglob zmv -CW ABC.* DEF.*'

1

これを行うことができます:

for i in ABC.*; do cp {ABC,DEF}."${i#*.}"; done

表示されていないものがありますが、複数の宛先を設定するにはどうすればよいですか?forループを使用してそれぞれを取得しています。事前にコードをテストしましたが、期待どおりに機能しましたので、ご理解いただければ幸いです。
サラファウジア14

それは私の悪いことです、私はあなたの答えを読み違えました。:
クリスダウン14

"${i#*.}"ビットをどのように読むべきですか?
-dumbledad

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.