2

この条件(-d $var)をループで使用して、指定されたディレクトリの子ディレクトリの数を確認しようとしましたが、代わりに一部のフォルダーがファイルとして検出されました。ディレクトリの認識に失敗した状態はどうなりましたか? この問題を解決するにはどうすればよいですか?

私のコードは次のとおりです。

foreach my $file (@files) {
    next if($file =~ m/^\./);
    if (-d $file and -e $file and !$seen{$file}) {
        $seen{$file} = 1;
        push @Dir, "$pwd/$file";
    }
    next if ($file !~ m/\s/i);
    my $new_name = s/\s//g;
    `mv $pwd/$file $pwd/$new_name`;
}
4

3 に答える 3

2

明らかなものは何も見えません。ただし、バグを発見しました。

  • あなたが持っていmy $new_name = s/\s//g;ます。=代わりに があります=~
  • $new_nameまた、置換を行うためにどのように取得するかについても言いません。

これらのどちらも、問題自体を指していません。

もう 1 つの可能性は、3 つの異なるテストをすべて AND 結合して使用することです。どういうわけか合格する条件に遭遇しているのだろうかと思います-dが、他の条件は当てはまりません。それらを分離したい場合があります。

$fileまた、ファイルがディレクトリであるかどうか@Dir$pwd. 何が起きてる?あなたもする必要がありif ( -d "$pwd/$file" )ますか?

問題が発生している場所を確認するために、いくつかのデバッグ ステートメントを挿入することをお勧めします。

これを試して:

use strict;
use warnings;

use feature qw(say);
use File::Copy;

my %seen;
my @dir;
for my $file ( @files ) {
    say qq(DEBUG: Looking at "$file");
    next if $seen{$file};
    say qq(DEBUG: "$file" has not been previously seen);
    $seen{$file} = 1;
    next if $file =~ /^\./;
    say qq(DEBUG: "$file" does not start with a period);
    if ( -d $file ) {
       say qq(DEBUG: "$file" is a directory);
       push @dir, "$pwd/$file;
    }
    else { #DEBUG:
       say qq(DEBUG: "$file" is a file);
   } #DEBUG:
   my $new_name = $file;
   if ( $new_name =~ s/\s+//g ) {
      say qq(DEBUG: Moving file "$file" to "$new_name");
      move $file, $new_name or
        die qq(Couldn't move "$file" to "$new_name");
   }
}
  • を使用use feature qw(say);すると、 コマンドを使用できますsay。これはprint、最後に新しい行を追加することを除いて、まったく同じです。
  • use File::Copyモジュールを使用すると、moveステートメントを使用できます。OS に依存する必要はもうありません。Perl には、生活を楽にする一連のモジュールが付属しています。たとえば、 をFile::Find使用すると、ファイルとディレクトリを検索できます。
  • すべてのファイルとディレクトリを含めて%seen(どうしてでしょうか?)、まずそれをチェックしてから、それがディレクトリであるかどうかをチェックします。
  • を使用しmove $file, $new_name or die qq(...)て、その move ステートメントが機能したかどうかを確認します。関数の出力を常にテストする必要があります。特に、ファイル名の移動やコピーなどの失敗しやすい関数です。
  • 私がすることに注意してくださいif ( $new_name =~ s/\s+//g )。これにより、スペースがあるかどうかをテスト$new_nameし、それらのスペースをすべて同時に削除できます。
  • qq(...)二重引用符に似ていますが、文字列内で引用符を逆引用符なしで使用できます。このようにして、ファイル名の末尾にスペースまたは NL があるかどうかを確認できます。

コードが機能するようになったら、文字列を簡単に検索しDEBUG:てノイズを除去できます。

私は自分のコードをテストしていません (プログラムが完全ではなく、データがどのように見えるかがわからない場合は難しいです) が、理解していただければ幸いです。ステートメントを使用DEBUG:すると、コードで何が起こっているかをより詳細に確認でき、ロジックの問題を見つけるのに役立ちます。約 1/2 の確率で、問題はプログラムではなくデータにあります。

于 2013-04-04T22:48:50.330 に答える
1

これは、これに似たスクリプトを書いている間、私に起こりました。File::Specメソッドでパス全体を使用してみてくださいcatfile。実際のファイルやディレクトリとは別のディレクトリでこれを実行していると想定しています。

use Cwd;
use File::Spec;

my $dir = getcwd; # Or whatever directory name you want
my $full_name = File::Spec->catfile($dir, $file);
if (-d $full_name) {
  # Do something
} 
于 2013-04-04T22:21:12.923 に答える