質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Perl

Perlは多目的に使用される実用性が高い動的プログラミング言語のひとつです。

UNIX

UNIXとは、AT&Tのベル研究所で開発されたコンピューター用のマルチユーザー・マルチタスクのオペレーションシステム(OS)です。政府や教育機関や研究所で広範囲に採用されています。

Q&A

解決済

4回答

4315閲覧

2つのディレクトリの中身(ファイル名)を比較&マージする。

happy

総合スコア9

Perl

Perlは多目的に使用される実用性が高い動的プログラミング言語のひとつです。

UNIX

UNIXとは、AT&Tのベル研究所で開発されたコンピューター用のマルチユーザー・マルチタスクのオペレーションシステム(OS)です。政府や教育機関や研究所で広範囲に採用されています。

0グッド

1クリップ

投稿2015/05/29 08:10

超、初心者です。よろしくお願いします。

やりたい操作は2つあります。

1:2つのディレクトリには各30個のファイルがあり、この2つのディレクトリを比較して、同じ名前のファイルを取り出す。

2:同じ名前のファイルをmargeし、新しいファイルとして新しいディレクトリに書き出す

2つのファイルをmargeするには、unixのコマンドのzcat(圧縮ファイルです。)を使用するとできそうです。
例 zcat fileA.fastq fileB.fastq >fileC.fastq

「別々のディレクトリから同じ名前のファイルを取り出す」というスクリプトが書けません(これはperlを使用したら良いのかなと思います)。また、zcat(Unixのコマンドと)とどのように組み合わせたら良いのか悩んでします。良いアイデア、スクリプトの書き方を教えていただければと思います。よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

1:2つのディレクトリには各30個のファイルがあり、この2つのディレクトリを比較して、同じ名前のファイルを取り出す。

ファイル名に改行を含んでいたりするとダメですが comm コマンドでできます。

comm -12 <(ls aaa/) <(ls bbb/)

例えば次のように片方のディレクトリには 10 から 39 までのフィアル名が、もう片方のディレクトリには 20 から 49 までのファイルがある場合、

mkdir aaa bbb touch aaa/{10..39} touch bbb/{20..49}

両方のディレクトリにある 20 から 39 までのファイル名が表示されます。

comm -12 <(ls aaa/) <(ls bbb/)

comm -23 なら aaa にだけ存在するファイル名が、

comm -23 <(ls aaa/) <(ls bbb/)

comm -13 なら bbb にだけ存在するファイル名が表示されます。

comm -13 <(ls aaa/) <(ls bbb/)

投稿2015/05/29 11:27

ngyuki

総合スコア4514

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

happy

2015/06/01 03:36

ありがとうございました。 comm コマンド、便利ですね。試してみたところ、ファイルを取り出すことができました。これから活用したいと思います。
guest

0

ベストアンサー

Perlではないですが、シェルスクリプト(これはshバージョン)でこのようにできます。
マージはテキストファイルを単純に連結する前提です。

lang

1#!/bin/sh 2 3for f in aaa/* 4do 5 name=`basename $f` 6 if [ -f bbb/$name ]; then 7 echo "merge $name" 8 cat aaa/$name bbb/$name > ccc/$name 9 fi 10done

aaabbbを比較し、マージ結果はcccに出力します。

foraaaと同じディレクトリーのファイル名の繰り返しを行います。
basenameで名前の部分だけを取り出します。
bbbにもその名前のファイルがあれば、マージします。
マージは、zcatでなくcatを使います。
zcatは、Compressで圧縮されたファイルを展開して標準出力に流すものです。

投稿2015/05/29 08:50

argius

総合スコア9388

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

happy

2015/06/01 03:35

遅くなりました。シェルスクリプトでもできるのですね。そしてシンプルなスクリプト、ありがとうございます。試してみたのですが、if 文の後の [-f bbb/$name] でエラーが出て、-f: command not found (-fというコマンドはない)と返されてしまいます ...。どのように変更したら良いでしょうか。
argius

2015/06/01 04:09

'['が認識されていないんでしょうか? ではとりあえずifの行を if test -f bbb/$name; then に書き換えるとどうでしょうか。
happy

2015/06/01 08:03

if test -f bbb/$name; then と書き換えたのですけど、うまくいかなかったのですが、 if test bbb/$name; then または、if [ bbb/$name ]; then とすると(-fを除いた)うまく動きました! 結果オーライな気もしますが、なぜ-fを入れるとエラーが出てしまったのでしょう? ....ともかく、目的の作業は完了しました!
argius

2015/06/01 08:11

目的を達成されたとのことで、安心しました。 今回はあえて環境について尋ねずに回答してしまったのが失敗だったかもしれません。 一部のUNIXやMacOSX,Linuxでは[ -f file ]で行けると思うんですけどね。 よろしければ下記ページを参照してみてください。 http://shellscript.sunone.me/if_and_test.html
guest

0

上記のPerlを書いたものです。
アルゴリズムがちょっとわかりづらくて混乱させてしまいました。

他の方がシェルでかかれたやり方のほうが、わかりやすいかもしれませんので、
そのPerl版を書きました。(一部systemで横着してます。。)

lang

1#!/usr/bin/perl 2use strict; 3use warnings; 4use File::Basename; 5 6my $dir1="dir1"; 7my $dir2="dir2"; 8my $dir3="dir3"; 9 10for( glob("$dir1/*") ) 11{ 12 my $name=basename($_); 13 if( -f "$dir2/$name" ) { 14 15 my $com = "cat $dir1/$name $dir2/$name > $dir3/$name"; 16 print $com,"\n"; 17 system( $com ); 18 } 19}

投稿2015/06/01 10:17

編集2015/06/01 10:55
frogman

総合スコア129

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

happy

2015/06/02 05:26

わざわざありがとうございます!このスクリプトでもうまく動きました。最後にsystemを使うと、perl上でシェルを実行できるのですね。これも一つのやり方ですね。勉強になりました。
guest

0

とりあえず、
「別々のディレクトリから同じ名前のファイルを取り出す」というスクリプト
です。

他にもやり方があるかと思いますが、とりあえずPerlで

my @array = ( glob("dir/"), glob("dir2/") );

のdir, dir2 部分を2つの任意のディレクトリ名で修正してください。

lang

1#!/usr/bin/perl 2use strict; 3use warnings; 4use File::Basename; 5 6my %hash=(); 7 8my @array = ( glob("dir/*"), glob("dir2/*") ); 9 10$hash{ basename($_) }++ for( @array ); 11 12 13while( my ($key, $val) = each %hash ) 14{ 15 print $key,"\n" if( $val == 2 ); 16}

投稿2015/05/29 14:54

編集2015/06/01 10:33
frogman

総合スコア129

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

happy

2015/06/01 03:41

perlのスクリプト、ありがとうございます!試してみたいのですが、whileを使った処理の部分が理解できません ..... 。解説していただけると助かります。不勉強ですみません ....。
frogman

2015/06/01 10:11

%hashは、ハッシュで、ファイル名がキー($key)になっています。 で、$valがファイル数。 ディレクトリ1とディレクトリ2のファイル名を足しているので、 ファイル数が2つだった場合は、ディレクトリ1とディレクトリ2で、同名のファイルが 存在していることになります。
happy

2015/06/02 04:51

なるほど!理解できました。操作もうまくできました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問