同じファイルをファイル名に規則性の無い複数のディレクトリにコピーするには

こんにちは。

似た質問が過去にありましたが、わからないので質問させていただきます。


あるファイルを、特定のディレクトリ以下のにある、全てのディレクトリの中の同じ名前のディレクトリにコピーする必要があるのですが、ターミナルでどのように入力すれば実現できるのでしょうか。


ターミナルを使う方法でも、オートメーターでもかまいません。

そんなソフトがもし有れば、教えていただけると助かります。


元データ

test/motodata.txt


コピー先ディレクトリ例

test/data/aiueo/text/

test/data/kakikukeko/text/

test/data/sashisuseso/text/

(aiueo,kakikukekoの部分は、何の規則性もありませんが、data/の中の全てのディレクトリです)

Mac OS X (10.6.6)

投稿日 2011/03/01 17:09

返信
返信: 48

2011/03/01 23:21 moominpapa への返信

上記の例に直すと、下記になります。

find ./data/*/*/text/motodata.txt -exec cp -f ./motodata.txt {} \;


また、この例は上書きにのみ使えるわけなのですが、もともと途中のディレクトリのみ存在して、ファイルが無い場合はどのように実現できるでしょうか? 


test/motodata.txt

コピー先のディレクトリ

/data/aiueo/a/text/

find path_data -name text -exec cp -f path_motodata.txt {} \;

最初のDirectoryの指定をしていないしtext folderの指定もなくて出来るとは考えにくい。

Fileが無くてもtext folderが見つかればCopyします。

# -type d -name text も試して下さい。


findをGoogleやmanで良く調べて行って下さい。Pathも大事です。

# Terminal コマンドのお勉強をされたほうが良いのでは...

2011/03/02 01:04 moominpapa への返信

コピーしたいファイル

test/motodata.txt

置き換えたいファイル

/data/aiueo/a/text/motodata.txt

/i/text/motodata.txt

/u/text/motodata.txt

/data/kakikukeko/ka/text/motodata.txt

/ki/text/motodata.txt

以下200~300続く

shellコマンドでもできるのかもしれませんが、複雑な処理をするときは、自分はperlを使います。


まずは、以下の内容のテキストファイルを作成し、cpall.pl の名前で test フォルダに保存します。

このとき、文字のエンコードは utf-8 としてください(日本語のファイルやフォルダも正しく扱えます)。

また、改行コードは LF としてください。


#!/usr/bin/perl

use utf8;

use File::Copy;

binmode STDOUT, ':utf8';

binmode STDIN, ':utf8';



$create_folder = 0;

$original = $ARGV[0];

utf8::decode($original);

(($original ne '') && (-e $original)) or die "Usage: cpall.pl source_file\n";



@dir_list = &find_folders('./data');

foreach my $par (sort @dir_list) {

my @sub_dir_list = &find_folders('./data/'.$par);

foreach (sort @sub_dir_list) {

my $text_exists = 1;

my $text_dir = "./data/$par/$_/text/";

unless (-d $text_dir) {

if ($create_folder) {

mkdir $text_dir;

unless (-d $text_dir) {

$text_exists = 0;

}

} else {

$text_exists = 0;

}

}

if ($text_exists) {

print "$text_dir ... ";

copy($original, "$text_dir/$original");

if (-e "$text_dir/$original") {

print "$original\n";

} else {

print "COPY ERROR\n";

}

} else {

print "$text_dir ... directory not found\n";

}

}

}



sub find_folders {

my @folders;

my $par = $_[0];

if (opendir my $in_dir, $par) {

my @list = readdir($in_dir);

closedir $in_dir;

foreach (@list) {

utf8::decode($_);

if ((-d $par.'/'.$_) && ($_ ne '.') && ($_ ne '..')) {

push (@folders, $_);

}

}

}

@folders;

}


次にターミナルを開き、test フォルダに cd してから、次のコマンドで cpall.pl を実行可にします。

hogehoge$ chmod 700 cpall.pl


次に次の要領で cpall.pl を実行します。

hogehoge$ ./cpall.pl motodata.txt


以上で、存在しているフォルダ全てに motodata.txt がコピーされます。

なお、7行目の $create_folder を 1 とすると、text フォルダがなかった場合には、作成してコピーを行います。


このコマンドを実行する場合には、コピー元のテキストファイルと、コピー対象となる複数フォルダが入っている data フォルダが同じ階層に入っている必要があります。また、コマンド実行時のカレントディレクトリも当該フォルダである必要があります。

必要に応じて使いやすいように修正してください。


perlプログラムの説明を始めるときりがないので、ここでは詳細は説明しません。

perlは特に文字データの処理に非常に強く、データ処理ツールとしてかなり強力です。

webのcgiもperlで書かれることが多く、送信されたフォームの正規化や定型処理にも使えます。

ちょっとした小道具をよく作るのであれば、知っていて損はないと思います。

2011/03/02 01:18 Hit-C への返信

具体例までありがとうございます。

おっしゃる通りです。perlも少しは理解したいと常々思っておりますが、何から始めたらよいやら…。


さて、試してみた所、下記エラーが出ました。


./cpall.pl: line 2: use: command not found

./cpall.pl: line 3: use: command not found

./cpall.pl: line 4: binmode: command not found

./cpall.pl: line 5: binmode: command not found

./cpall.pl: line 7: =: command not found

./cpall.pl: line 8: =: command not found

./cpall.pl: line 9: syntax error near unexpected token `$original'

./cpall.pl: line 9: ` utf8::decode($original);'

2011/03/02 01:27 moominpapa への返信

useが使えないはずはありません。

ターミナルで、

/usr/bin/perl --version

コマンドを実行すると、どのように表示されますか?


また、

#!/usr/bin/perl

print "Hello!\n";

の2行だけの test.pl ファイルを作成して、

./test.pl

を実行したら、正常に Hello! が表示されますか?


もし、ここからコピペしているのであれば、余計なコードが入ってしまっているかもしれません。

まずは、上記の2行のテストコードは手打ちで試してみてください。

正常に動作するなら、コピペで試してみてください。

2011/03/02 01:41 Hit-C への返信

よく読んでないのですが、よほど古いOSXでない限り、perl は自動的にutf8を使います(5.8以上?)ので、ファイル名のエンコーディングは気にしなくてもよいと思います(OSXはもともとutf8を利用してます。現在広く使われているOSは、内部的には、ほとんどutf8を使ってます。Windows だけは、表示は今でもsjis?)。

なので、perl で無造作にcopyとかしても、日本語ファイル名がおかしくなることはありません。

2011/03/02 01:46 Hit-C への返信

Hit-C様


$ /usr/bin/perl --version


結果

This is perl, v5.10.0 built for darwin-thread-multi-2level

(with 2 registered patches, see perl -V for more detail)


コピペでtest.plを作成して、実行してみました。

$ ./test.pl


結果

Hello!

良好


余計なコード探し

各行頭に半角スペースが4~8程度入っていたので、全部削除してみたところ動きました!

何年も困っていたので、本当に助かりました。これで地味でひたすら長い作業から開放されそうです。


お時間割いていただき、ありがとうございました。

他の皆さんも、アドバイスありがとうございました。

2011/03/02 02:30 moominpapa への返信

#! /bin/bash

find ~/Desktop/data -name text -exec cp -f ~/Desktop/motodata.txt {} \;


motodata.txt CopyするFile

/data/aiueo/a/text/motodata.txt

/data/aiueo/i/text/motodata.txt

/data/aiueo/u/text/motodata.txt

/data/kakikukeko/ka/text/motodata.txt

/data/kakikukeko/ki/text/motodata.txt


Desktopに上記モデルを作って試しました。AutomatorのRun Shell Scriptを使えばfindの行だけで動くと思います。CopyするFileと実際に使うPathを修正すれば良いと思います。

2011/03/02 02:50 ぴっぴ への返信

ぴっぴさん

ありがとうございます。


#! /bin/bash

find ~/Desktop/data -name text -exec cp -f ~/Desktop/motodata.txt {} \;


うまく動作しました。


Autometorに、Run Shell Scriptというのが見つからないのですが、

カタカナでした。「シェルスクリプトを実行」。こんなの有ったんですね。


Autometorでは動作時にコピーするファイルと、コピーした先の親ディレクトリが指定できると本当に良いのですが、なんだかこのあたり頑張れば、出来そうな気が…。

2011/03/02 03:06 moominpapa への返信

解決済みではありますが、私もAutomatorを試して見ました。

ファイルパスはテキストでなら取り出せましたが、コピー先に指定する方法が見つかりません。変数に収納して試しましたが、最初に見つかったtextフォルダにコピーするのみでした。

もし可能になったとしても大量(200を超えるあたりからでしょうか。)のファイルやフォルダをAutomatorで扱うと途中で止まってしまう可能性があります。ただ、今回ファイルパスがテキストで取り出せる事に気付いたのは私にとっては収穫でした。(findでも出来てしまうのですが^^)

2011/03/02 03:12 ni_ki への返信

Autometorを使った解決方法も引き続き募集しています。


ところで、始めてなので作法がわからなかったのですが、正解を付けてしまうと、他にもう役に立つとか、もっといい正解とか書けないのですね。


ぴっぴさんの解が、今回一番良いかと思うのですが、[正解としてマーク解除]を押しても反応ありません。Firefox、SafariともにNGでした。

2011/03/02 03:34 moominpapa への返信

Autometorでは動作時にコピーするファイルと、コピーした先の親ディレクトリが指定できると本当に良いのですが、なんだかこのあたり頑張れば、出来そうな気が…。

Automatorだとプロンプトが面倒ですがShell Scriptなら簡単です。

あるいは必要なShell Scriptを幾つか作っても良いのでは?


#! /bin/bash

echo "directory?"; read DIR

echo "file?"; read DATA

if [ "$DIR" = "" ]; then exit

elif [ "$DATA" = "" ]; then exit

else

find $DIR -name text -exec cp -f $DATA {} \;

fi


簡単なError処理ですが動くと思います。

2011/03/02 04:01 ぴっぴ への返信

ぴっぴ様

コレすごいですね!


ファイル名と、ディレクトリ名をその都度聞かれるので、その都度自由が利きます。


1. テキストエディタで、上記を入力し、test/copytest.sh で保存

2. cd test する

3. chmod 777 copytest.sh

3. ./copytest.sh

4. directory? と聞かれるので、 ./data を指定

5. file? と聞かれるので、./motodata.txt を指定

終わり。



/usr/bin/sh にでも保存して、パスを通しておけばいつでも呼び出しできるというわけですね。

すばらしい回答ありがとうございました!



…引き続き、Automatorを使った方法もお待ちしております。

このスレッドはシステム、またはAppleコミュニティチームによってロックされました。 問題解決の参考になる情報であれば、どの投稿にでも投票いただけます。またコミュニティで他の回答を検索することもできます。

同じファイルをファイル名に規則性の無い複数のディレクトリにコピーするには

Apple サポートコミュニティへようこそ
Apple ユーザ同士でお使いの製品について助け合うフォーラムです。Apple Account を使ってご参加ください。