in reply to Problem with command-line option parsing

Previous nodes in this thread have already addressed the question at hand recommending the usage of the Getopt modules, Getopt::Std and Getopt::Long, for the parsing of command line options. However, upon reading the root node of this thread, I thought I could have a bit of fun in posting my own reply ...

Firstly let me state, that I do not recommend the use of any of the techniques discussed below in a production environment - Please, please, please follow some of the more sane advice given in the thread above.

That having been said, I offer the following obfuscated solution which performs all of the tasks of the previously posted code - Please note that this code is not strict compliant, uses no if-else-unless control structures and is generally evil by all measures, for therein lies the fun ...

#!/usr/bin/perl -s opendir+D,pop;$.=pop;$,=pop;for(grep{-f $_}readdir(D)){$;=$_;s=$,=$.=;(!defined $q||defined$i)&&print"$; $_";(defined$i ) && do{print" y/n?";$y = <STDIN>;($y=~ /^y/i)&&++$force;}; (!defined$q)&&print "\n";defined$force&&rename$;,$_}

The code snippet above makes use of the -s switch to the perl executable which enables rudimentary parsing of command line arguments passed to a script - This argument enables rudimentary switch parsing on the command line after the script name but before any filename arguments (or before a --). Any switch found is removed from @ARGV and a variable with a corresponding name is set.

For a discussion about this and other alternate forms of command line argument parsing, see Poor's man command line arguments.

With this rudimentary form of command line parsing, if the command line arguments -force, -i and -q are passed to this script, the corresponding variables $force, $i and $q are set - These variables are used to control the behaviour of the above script (without the use of any if, unless or while control statements).

How does this script work? Well ...

opendir+D,pop; $.=pop; $,=pop;

After this parsing of command line arguments, this code pop's the directory passed to this script from @ARGV and then does the same for the replacement and search patterns, storing these values in the input record separator, $., and the output record separator, $,, respectively.

for(grep{-f$_}readdir(D)){ ... }

The list of files in this directory, as determined by grep-ing through the list of elements returned by readdir and testing each with the -f (file) file test, is looped through - It is in this loop that the majority of work of this script is performed:

$;=$_; s=$,=$.=;

The original file name is stored in the variable used as the subscript separator for multidimensional array emulation, $;, while the default variable, $_, is modified by the search and replace pattern, using the values previously stored in the input and output record separators. The = character is used in place of the / character for the separating of the search and replacement pattern in the substitution function.

(!defined$q||defined$i)&&print"$; $_";

The old and new filenames are printed if either the quiet command line argument (-q) is not specified or the interactive command line argument (-i) is specified.

(defined$i)&&do{ .. }

If the interactive command line argument (-i) is defined, a block containing code to prompt for user input is executed. The code which is executed is the following:

print" y/n?";$y=<STDIN>;($y=~/^y/i)&&++$force;

This code prints the text " y/n?", prompts for user input and if the reply starts with the letter 'y', increment the $force variable. This variable has been used so that only a single rename function is required for renaming the file, irrelevant of whether this is specified by user input in interactive form or by specification of the -force command line argument (see the discussion on rudimentary command line argument parsing using the -s argument to the perl executable).

(!defined$q)&&print"\n";

Print a trailing new line if the quiet command line argument (-q) is not specified.

defined$force&&rename$;,$_

Finally, the file is renamed if the $force variable is set, either within the user interactive mode described above or by the -force command line argument.

Yes, I am evil ... :-)

 

perl -le 'print+unpack("N",pack("B32","00000000000000000000001000010010"))'