How do I define new make tasks, using `Makefile.PL`? - perl

I would like my generated Makefile to have these new tasks for linting:
perl:
-for f in **/*.pl; do perl -MO=Lint -cw $$f 2>&1 | grep -v "syntax OK"; done
-for f in **/*.pm; do perl -MO=Lint -cw $$f 2>&1 | grep -v "syntax OK"; done
perlcritic:
-perlcritic . | grep -v "source OK"
lint: perl perlcritic
I tried writing a Makefile.PL, but when I run it, the resulting Makefile still lacks the lint task.
use ExtUtils::MakeMaker;
sub MY::lint {
return <<'END';
lint:
echo "Linting!!!!!!!!!!!1"
END
}
WriteMakefile;
I tried reading the CPAN docs, but like most docs, they give snippets without sufficient context, so I'm not even sure if I should declare the subs before or after WriteMakefile.
Also posted on Reddit.

Thanks to briandfoy:
$ cat Makefile.PL
#!/usr/bin/env perl
use strict;
use warnings;
use ExtUtils::MakeMaker;
WriteMakefile;
sub MY::postamble {
return <<'END';
perlwarn:
-find . -type f -name '*.pl' -exec perl -MO=Lint -cw {} 2>&1 \; | grep -v "syntax OK" | grep -v "Can't locate"
-find . -type f -name '*.pm' -exec perl -MO=Lint -cw {} 2>&1 \; | grep -v "syntax OK" | grep -v "Can't locate"
-find . -type f -name '*.t' -exec perl -MO=Lint -cw {} 2>&1 \; | grep -v "syntax OK" | grep -v "Can't locate"
perlcritic:
-perlcritic . | grep -v "source OK"
lint: perlwarn perlcritic
END
}

A solution that works and is slightly easier to maintain is to put the make targets in a separate makefile, so you can benefit of your text editor capabilities and it is a bit easier to read:
# In Makefile.PL
use File::Slurp;
sub MY::postamble {
my $targets = read_file('./script/additional.make');
return $targets;
}
# In /script/additional.make
perl:
for f in **/*.pl; do perl -MO=Lint -cw $$f 2>&1 | grep -v "syntax OK"; done
for f in **/*.pm; do perl -MO=Lint -cw $$f 2>&1 | grep -v "syntax OK"; done
perlcritic:
perlcritic . | grep -v "source OK"
lint: perl perlcritic
Note for later readers: I am using Module::Install and it was necessary to use :: as separators because it seems that Module::Install forbid to mix : and ::. It also disallow the use of -.

Related

find -ctime bash alternative in Perl

Kind of new to Perl, still navigating my way through.
Is there another way to write the bash command below in "Perl"?
find $INPUT_DIR -ctime -$DAYS_NUM -type f -exec grep -hs EDI_DC {} \; |
grep -i -v xml >> $OUTPUT_DIR/$OUTPUT_FILENAME
where INPUT_DIR, DAYS_NUM, OUTPUT_DIR and OUTPUT_FILENAME are arguments passed during runtime.
When you try to convert find command to perl, consider using find2perl script.
It generate the perl code.
find2perl 'INPUT_DIR' -ctime -'DAYS_NUM' -type f -exec grep -hs EDI_DC {} \;

Understanding the line that calls the file name

I do not understand the line that calls the file name.
#!/bin/sh
cd Desktop/Test/xml_replace
find . -name "*.xml" -print | while IFS= read -r file; do echo "$file"
perl -pi -e 's/&/&/' $file

Can find tell me if no files exist?

On my FTP server, I look for files delivered in the past day and remove in-place header & trailer records.
find . -type f -name "CDC*" -ctime -1 -exec sed -i'' -e '1d' -e '$d' '{}' \;
This works well.
I want to automate this in a script. But how can I send myself an email notification is no files are found? I am thinking of doing something like:
find . -type f -name "CDC*" -ctime -1 -exec sed -i'' -e '1d' -e '$d' '{}' \;
EXIT=`echo $?`
case $EXIT in
0) ...do stuff...
*) mail....exit
esac;;
There has to a better way, right?
I'm pretty sure that you could take whatever command you need to do the search, and pipe a wc -l on to the end of it. Then use an if statement to check for zero. So using your example above.
NUMLINES=`find . -type f -name "CDC*" -ctime -1 -exec sed -i'' -e '1d' -e '$d' '{}' \ | wc -l`
if [ "$NUMLINES" -eq 0 ] ; then
foo
fi
Or something like that. I didn't check if that syntax is correct though. But i'm sure you get my drift

find command for the newest 500 files in a directory tree and also be POSIX compliant

I'm looking for a single line shell script or unix command to find the newest 500 files in a directory tree. Major constraints are it should be POSIX compliant and the directory can have tons of files.
I found from the below link a perl script which helped:
find . -type f -print | perl -l -ne ' $_{$_} = -M; END { $,="\n"; print sort {$_{$b} <=> $_{$a}} keys %_ }' | head -n 500
How to recursively find and list the latest modified files in a directory with subdirectories and times?
Any more comments most welcome.Thanks all.
How about this:
Posix ls and head
ls -tc DIR | head -n 500
find . -type f -print | perl -l -ne ' ${$} = -M; END { $,="\n"; print sort {${$b} <=> ${$a}} keys %_ }' | head -n 500
It should be the contrary for the sort ${$a} <=> ${$b}
The head can be avoided: print+(...)[0..499]
The find too with a recursive call:
perl -e 'sub R{($_)=#_;map{-d$_?&R($_):$_}<$_/*>}print$_,$/for(sort{-M$a<=>-M$b}R".")[0..499]'
Or with an unix cmd: not sure if there are to many arguments may fail
find . -type f -exec ls -1t {} + | head -500
find . -type f -print0 | xargs -0 ls -1t | head -500
find . -type f -exec stat -c %Y:%n {} \; |
sort -rn | sed -e 's/.*://' -e 500q
This sorts on ctime, which can be changed by using %Z or %X in the format string, but stat is not POSIX.
There is no 100% reliable POSIX way of doing this with shell scripting.
A POSIX C program will do it easily though, assuming you define newest by either last modified file content or last changed file. If you mean last creation time, there is no POSIX way and possibly no solution at all, depending on the file system used.

How can I check whether a piped content is text with perl

I've written a svn-hook for text files. The content test looks like this:
svnlook cat -t $txn $repos $file 2>/dev/null | file - | egrep -q 'text$'
and I was wondering if this could be done with Perl. However something like this doesn't work:
svnlook cat -t $txn $repos $file 2>/dev/null | perl -wnl -e '-T' -
I'm testing the exit status of this invocation ($?) to see if the given file was text or binary. Since I'm getting the content out of svn. I can't use perl's normal file check.
I've done a simulation with the file program and perl with a text and binary file (text.txt, icon.png):
find -type f | xargs -i /bin/bash -c 'if $(cat {} | file - | egrep -q "text$"); then echo "{}: text"; else echo "{}: binary"; fi'
./text.txt: text
./icons.png: binary
find -type f | xargs -i /bin/bash -c 'if $(cat {} | perl -wln -e "-T;"); then echo "{}: text"; else echo "{}: binary"; fi'
./text.txt: text
./icons.png: text
You're testing perl's exit code, but you never set it. You need
perl -le'exit(-T STDIN ?0:1)' < file