#!/usr/bin/perl
use strict; use warnings;
foreach my $file (glob('*')) {
unless (-s $file) {
print "$file\n";
}
}
How do I output names of empty files in the current directory?
Frage
I’m trying to check my folder for files that are empty (0 bytes). I have about 1,200 files so Perl will make this task very easy :)
Here is my code so far but it doesn't seem to work. (It’s just listing all of the files.) Can anyone teach me what I’ve done wrong? Thanks!
#!/usr/bin/perl
@files = glob('*');
if ((-s @files) == 0) {
print"@files\n";
}
Lösung 2
Andere Tipps
You do one check, yet you have multiple files. Obviously, that makes no sense. You need to add a loop to check each file.
#!/usr/bin/perl
use strict;
use warnings;
my @files = grep { -s $_ == 0 } glob('*');
# or: grep { ! -s $_ }
# or: grep { -z $_ }
# or: grep { -z }
# or: grep -z,
print "@files\n";
In your version, you are attempting to get the size of the file named 12
or whatever the number of elements of @files
is. As a result, -s
was returning undef
with $!{ENOENT}
set.
yet another way of doing things in perl
use File::stat;
foreach (glob('*')){
print stat($_)->size,"\n"
};
# this will file sizes of all files and directories
# you need to check if its a file and if size is zero
I recommend a solution much like all the others, but I recomment that you use the -z operator rather than the -s operator.
In my mind, it is clearer to code "if the file is zero length" as opposed to "unless the file has non-zero length"
Both have the same boolean meaning, but the former codes your intent more clearly. Otherwise, the answers you've been getting are all pretty good.
#/run/my/perl
use strict;
use warnings;
foreach my $file ( glob("*") ) {
print "$file\n" if -z $file;
}
To see how it is done when searching all levels beneath the current directory, consider the output of the standard tool find2perl
.
$ find2perl . -type f -size 0c
#! /usr/bin/perl -w
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
if 0; #$running_under_some_shell
use strict;
use File::Find ();
# Set the variable $File::Find::dont_use_nlink if you're using AFS,
# since AFS cheats.
# for the convenience of &wanted calls, including -eval statements:
use vars qw/*name *dir *prune/;
*name = *File::Find::name;
*dir = *File::Find::dir;
*prune = *File::Find::prune;
sub wanted;
# Traverse desired filesystems
File::Find::find({wanted => \&wanted}, '.');
exit;
sub wanted {
my ($dev,$ino,$mode,$nlink,$uid,$gid);
(($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
-f _ &&
(int(-s _) == 0)
&& print("$name\n");
}
Run the code above with
$ find2perl . -type f -size 0c | perl
Adapting this knowledge to your situation
my @files = grep -f $_ && -s _ == 0, glob "*";
print @files, "\n";
or in a single call to print
with
print +(grep -f $_ && -z _, <*>), "\n";
Using the special _
filehandle that holds a cached copy of the most recent stat
result avoids making two traps into the operating system where one will suffice. Note the extra check that the file is a plain file (-f
) that is necessary because the zero-size check—either -s _ == 0
or -z _
—will return true for empty directories on some filesystems.