
Perl で特定のフォルダ以外を削除したいのですが
普通はフォルダを指定して削除するところを
rmdir "log/delete";
上記のように削除させますが
ディレクトリ構造↓
log----1/
-------2/
-------3/
-------4/
-------5/
-------delete/
-------log.txt
上記のlog.txtの中身↓
1
2
3
4
5
-------------------
のように連番が振ってあり
その連番と同じフォルダがなければ削除
と今回の場合
deleteフォルダがないので
それを削除させたいのですが、
rmdir "log/delete";
↑これではなく
1,2,3,4,5を残し、それ以外のフォルダを削除
という指定にしたいのですが
どのようにすればいいでしょうか?
No.6ベストアンサー
- 回答日時:
さすがに #1 に書いたようなスクリプトだと保守性が悪すぎるので, 最後の
remove_tree grep { -d; } map { "$parent_dir/$_"; } grep { my $f = $_; $f ne "." && $f ne ".." && ! grep { $_ eq $f; } @preserve_dirs; } readdir DH;
は
for my $f (readdir DH) {
next if $f eq '.';
next if $f eq '..';
next if grep { $_ eq $f; } @preserve_dirs;
my $d = "$parent_dir/$f"; #ここも File::Spec::catfile を使う方が安全?
remove_tree $d if -d $d;
}
くらいのループにすべきですけどね. あれは
その気になればこのくらい圧縮できる
という (無意味かつ悪い) 実例ですから.
なるほどなるほど
一度フォルダ内のリストを取得させ
そこから「.」「..」をまずはぶき
フォルダ内=配列のものをgrepさせ
最後にリストに内ものを削除するのですね!
File::Spec::catfil
↑初めて見ました
↓これですね。。
http://search.cpan.org/~xsawyerx/PathTools-3.74/ …
おおよそ理解できてきたので、↑のモジュールは自分と勉強して
使えるようにしたいと思います!
ありがとうございました!!
No.5
- 回答日時:
正直にいわせてもらうと, grep や map を理解していないんじゃないかなと思う.
あと「前回の処理だと1つのファイルしか削除されなかった」はなにかを勘違いしてるんじゃないだろうか. 少なくとも手元ではちゃんと「log.txt に書かれていないディレクトリ」を一度で全部消してる.
たしかにそうでした。
ただ、上手く説明できませんが・・・
@preserve_dirs
この子が対象だということですね
use File::Path;
↓
use File::Path 'remove_tree';
これにするだけで解決でした。
ここまでの仮定で、余計なForを入れてるからおかしなことになっていたのですね。
No.4
- 回答日時:
え.... 問題ないというか, ほぼ「問題しかない」んですが....
何をやっているか, 理解できていますか? 自分の言葉で説明できますか?
なんですって・・・;;
まだまだ理解できてませんねorz
my $parent_dir = "log";
my @preserve_dirs;
open FH, "$parent_dir/log.txt";
chomp(@preserve_dirs = <FH>);
#▲ここで、log.txtの中身を取得
my $dir_serch="./log/";
my @Kosu;
opendir(DIR, "$dir_serch");
my @file = readdir(DIR);
foreach (@file) {
push @Kosu , "$_\n";
}
closedir(DIR);
#▲無理やりではありますが、フォルダ内の名前を取り出し
#▼下のループの最後まで $#Kousu = [.][..]も含んだままなので
#ループ処理が多くなってますが。。
for(my $fd=0;$fd<=$#Kosu;$fd++){
opendir DH, $parent_dir;
remove_tree grep { -d; }
map { "$parent_dir/$_"; }
grep { my $f = $_; $f ne "." && $f ne ".." &&
! grep { $_ eq $f; } @preserve_dirs; } readdir DH;
closedir DH;
}
#質問には含めていませんでしたが、
#前回の処理だと1つのファイルしか削除されなかったので、
#複数消したかったため、ループ処理を加えておりました・・・
No.3
- 回答日時:
動作はそれで OK のはず. ただし
http://perldoc.perl.org/File/Path.html
によると rmtree は古い形式 (超意訳) なので, そこは remove_tree の方が安全かと.
grep や map は
・grep: 配列から指定した条件を満たす要素を取り出し配列として返す
・map: 配列の各要素に対して処理した結果を配列として返す
という動作.
それからついでに
chomp(@preserve_dirs = <FH>);
を
%preserve_dirs = ('.' => 1, '..' => 1, map { chomp; $_ => 1; } <FH>);
のようにハッシュにしておけばあとの
grep { my $f = $_; $f ne "." && $f ne ".." && ! grep { $_ eq $f; } @preserve_dirs; } readdir DH
を
grep { ! $preserve_dirs{$_}; } readdir DH
と短縮できることに一晩寝て気付いた.
と書いておくけど, 本当に実用とするのであればこんなに grep や map をばんばか使うんじゃなくっててきせつなループにすべきだと思う.
なるほど!
ただ、ハッシュの仕組みが未だに理解できていないので、今は使わないようにしておきます・・・
ループ処理をヒントに
最終的に
use strict;
use warnings;
use File::Path 'remove_tree';
my $parent_dir = "log";
my @preserve_dirs;
open FH, "$parent_dir/log.txt";
chomp(@preserve_dirs = <FH>);
my $dir_serch="./log/";
my @Kosu;
opendir(DIR, "$dir_serch");
my @file = readdir(DIR);
foreach (@file) {
push @Kosu , "$_\n";
}
closedir(DIR);
for(my $fd=0;$fd<=$#Kosu;$fd++){
my $Ko = $Kosu[$fd];
opendir DH, $parent_dir;
remove_tree grep { -d; }
map { "$parent_dir/$_"; }
grep { my $f = $_; $f ne "." && $f ne ".." &&
! grep { $_ eq $f; } @preserve_dirs; } readdir DH;
closedir DH;
}
close FH;
このようになりましたが、問題ないでしょうか・・・?
No.2
- 回答日時:
直すのはもちろん直せるんだけど, どのようなことをしようとしているか理解できているのですか?
ある程度は理解しているつもりではありますが・・・
自信はありません・・・
$parent_dir = "log";
open FH, "$parent_dir/log.txt";
chomp(@preserve_dirs = <FH>);
close FH;
これはログテキスト内の列を取得し、配列へ
でもここがわからないです
remove_tree grep { -d; }
↑これはわからない
フォルダを削除だと思うのですが、初めて見ました・・・→「remove_tree」
map { "$parent_dir/$_"; }
↑これもわからない
?log/ ←内のフォルダのリスト化?
grep { my $f = $_; $f ne "." && $f ne ".." && ! grep { $_ eq $f; } @preserve_dirs; }
おそらくこれする前を、print表示すると
----------------------------------------
.
..
1
2
3
4
5
delete
----------------------------------------
↓これを
----------------------------------------
1
2
3
4
5
----------------------------------------
[.][..]はフォルダーパス取得したときに付与されている?のと
! grep { $_ eq $f; } ログファイル内と、フォルダリストがイコールでないやつ
ということでしょうか?
初めてみた→「remove_tree」
でググっているうちに
↓にたどり着き
use File::Path; → use File::Path 'rmtree';
remove_tree → rmtree
に変更させると実行はできたのですが、
正しいでしょうか?
No.1
- 回答日時:
use File::Path;
$parent_dir = "log";
open FH, "$parent_dir/log.txt";
chomp(@preserve_dirs = <FH>);
close FH;
opendir DH, $parent_dir;
remove_tree grep { -d; } map { "$parent_dir/$_"; } grep { my $f = $_; $f ne "." && $f ne ".." && ! grep { $_ eq $f; } @preserve_dirs; } readdir DH;
closedir DH;
みたいな感じ?
ソースご掲示ありがとうございます。
実行してみたのですが
下記のようなエラーがでたのですが、
Use of my $_ is experimental at test.pl line 7.
Use of my $_ is experimental at test.pl line 7.
syntax error at test.pl line 7, near "remove_tree
grep"
syntax error at test.pl line 7, near "; }"
Execution of test.pl aborted due to compilation er
rors.
どういうことでしょうか・・?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
複数ファイル?処理させる方法...
-
Windowsで複数のファイルを同じ...
-
エラー 'dir.h' : No such fi...
-
FindFirstFileとFindNextFileで...
-
readdir()で得られるファイル・...
-
batファイルでrenameができませ...
-
vba dir の相対パス
-
エクセルVBA コードが同じでも...
-
MATLAB グローバル変数の宣言
-
ファイル全てを .xlsm に変更し...
-
[Perl]ファイル出力のエンコー...
-
ExcelをCSV書き出す場合のシー...
-
openした後、closeしないでプロ...
-
JavaでCSVファイルを高速に読む...
-
VBAでCSVファイルを途中行まで...
-
[Perl]Shift-JISのXMLを解析する場
-
sprintfについて
-
「パスが見つかりません」とい...
-
csvファイル改行コードの置換に...
-
外部サーバーにあるファイルを...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Windowsで複数のファイルを同じ...
-
batファイルでrenameができませ...
-
vba dir の相対パス
-
パスから最後のディレクトリだ...
-
FindFirstFileとFindNextFileで...
-
readdir()で得られるファイル・...
-
ディレクトリー内のリスト出力...
-
ファイル名と更新日付の取得に...
-
C言語でファイル名を取得
-
ファイルの削除について
-
シェルでfind結果を文字列で比...
-
dos変数の%~dp0は powershellで...
-
フォルダに入っているファイル...
-
サーバー内にある指定した拡張...
-
CGIで日本語名ファイルのアップ...
-
find関数が1階層(カレントディ...
-
下のディレクトリ(3つ)に含ま...
-
ファイル名が日本語の物をダウ...
-
<>の意味が分かりません
-
makefileでファイルをコピー(...
おすすめ情報