![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
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で質問しましょう!
似たような質問が見つかりました
- ノートパソコン pcでフォルダをDeleteで削除しようとしたのですが、別のフォルダを削除する所だったので急いでキャ 6 2022/12/05 16:56
- Excel(エクセル) 2つのマクロを連続して動かしたい 3 2022/09/20 23:46
- Outlook(アウトルック) すべての新着メールが「受診フォルダ」に入らない。 2 2023/02/24 20:28
- Visual Basic(VBA) エクセルのマクロについて教えてください。 2 2023/07/06 17:46
- Visual Basic(VBA) エクセルのマクロについて教えてください マクロを実行すると メッセージボックスが表示されて okをク 4 2023/07/05 19:32
- Excel(エクセル) マクロのコードを、少しでも削って短くしたい 3 2022/08/30 07:46
- Visual Basic(VBA) フォルダの場所を可変にしたいです(マクロ) 4 2023/05/11 10:00
- その他(クラウドサービス・オンラインストレージ) OneDriveで特定のフォルダ(写真だと、スクリーンショット)の内容だけをバックアップしない方法を 2 2022/05/20 01:44
- Visual Basic(VBA) エクセルのマクロについて教えてください。 3 2023/07/01 10:35
- サーバー windowsサーバの権限設定、フォルダ削除できないアカウントを作りたい 1 2023/04/07 09:58
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
dos変数の%~dp0は powershellで...
-
Windowsで複数のファイルを同じ...
-
ディレクトリ名を取得したい
-
chdirがうまくできない
-
vba dir の相対パス
-
<>の意味が分かりません
-
C言語でファイル名を取得
-
ExcelをCSV書き出す場合のシー...
-
VBAでCSVファイルを途中行まで...
-
window.open でのファイル指定方法
-
ReadLineでの読み出し行を指定する
-
openした後、closeしないでプロ...
-
perlで複数行のデータを自由に...
-
sprintfについて
-
microsoft multimedia control ...
-
改行コードが勝手に
-
ADOによるCSVファイルからのデ...
-
fopenでディレクトリ内の全ファ...
-
htaccessで特定のディレクトリ...
-
バッチファイルの作り方(CSV→...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
batファイルでrenameができませ...
-
C言語でファイル名を取得
-
FindFirstFileとFindNextFileで...
-
パスから最後のディレクトリだ...
-
vba dir の相対パス
-
readdir()で得られるファイル・...
-
Windowsで複数のファイルを同じ...
-
エラー 'dir.h' : No such fi...
-
ディレクトリ名を取得したい
-
dos変数の%~dp0は powershellで...
-
一定時間が経過したフォルダの削除
-
find関数が1階層(カレントディ...
-
複数ファイルの読み込みについて
-
ディレクトリ内CSVデータをすべ...
-
テキストファイルの結合
-
perlのNet::FTPで、ファイルか...
-
ファイル名の変更
-
chdirがうまくできない
-
下のディレクトリ(3つ)に含ま...
-
コマンド「dir」の結果を、テキ...
おすすめ情報