The example program has a forever loop
The first argument for opendir is a ‘directory handle’, this gets set by the opendir function; the second argument is the pathname for the directory.
Users vary in how they name directories; most just give the directory name, but some have the habit of adding a trailing ‘/’; in order to standardize prior to later steps, any trailing ‘/’ character is removed in the pattern substitution step – $directory =~ s#/$##.
The call readdir DIRHANDLE; returns a list with all the entries in the directory accessed via the directory handle. Each element in the list is processed in the following foreach loop. The entries ‘.’ and ‘..’ are ignored – the regular expression specifies a pattern of any number of ‘.’ characters taking up an entire line (from ^ start to $ end). Before the file tests are made, the names of the entries have to be built up to fully specified names incorporating a complete directory path. The fully qualified filenames are obtained by prepending the directory name to the entry name.
The first two tests use the -d and -l file-test operators to test for a directory and a link respectively (if(-d $fullname) …). If an entry is a simple file, -x and -T tests can be used to obtain information about it. (Is the executable-bit set? Is it a text file? A file could be both if it is a script.)
The opendir and readdir functions probably represent the easiest way of working with the contents of a directory; but, of course, with Perl there is always another way! Actually, there are two other ways of getting lists of files in directories, and you can use stat function on files to get lots and lots of extraneous information about a file.
An alternative to readdir is the use of shell-style patterns to specify the desired entries in a directory. These shell-style patterns bear a superficial resemblance to regular expressions, but be careful as the meanings of symbols do differ. The shell pattern ‘*’ is used to request every entry in a directory (well, not everything – entry names starting with ‘.’ are excluded): a pattern like ‘*.pl’means all Perl scripts; while a shell pattern like [AB]*.cc means all cc files whose names start with either A or B. These shell patterns can be used either with the diamond (< >)input file operator or the glob function (see the perlfunc and perlop documentation for more details and subtle differences between these forms of use).
This version uses chdir to change the current working directory to that specified in the input. The shell pattern ‘*’ (all files) is then used with the diamond operator in a foreach loop; this results in the anonymous variable $_ being bound to the names of the successive entries in the current directory; these names are returned as fully qualified pathnames.
The file tests, if( -d )…, and the file size assignment, $size = -s, implicitly reference the anonymous variable $_. Such code is often cutely concise; but remember, code is generally ‘wormy’ (‘write once, read many’). Too many linguistic tricks involving anonymous variables can present major problems to maintenance programmers. So be sparing with your use of Perl tricks.
Perl core has the main file manipulation programs: rename, unlink, chmod, mkdir, rmdir. Most of these functions take a filename argument (either the name of a file in the current working directory, or a fully qualified pathname).
