Finding Files with Perl on a Hidden Dir?

Greetings!

Been a while since I futzed around with Perl, and came upon a minor headscratcher for the community :wink:

Here's the basic code which I'm trying to make tick over:

#!/usr/bin/perl

use strict;
use warnings;
use diagnostics;

print " starting ";
while (-e "~/.somedir/testFile")
{
    print " file detected ";
    sleep 1;
}
print " file missing ";

exit;

Queerly, this will not work on hidden (.somedir) dirs!

So, not being one to give up too easily, I even tried passing a couple bashlines to the system as well. Here are the better substitute "while" statements which I tried:

while (`wc -l ~/.somedir/testFile | sed -e 's/ \/.*$//'` eq "0")
while (`ls -a ~/.somedir | grep -e \"testFile\"` eq "testFile")

Of course, none of these worked in our Perl context :frowning:

Any ideas for a "simple" solution amended from this rag-tag assortment would be quite appreciated!

Thanks again --

I commend you for making use of the pragmas strict , warnings and diagnosis , especially, when you are troubleshooting/learning.
Still, I wish you would had declared your purpose. It is not clear by looking at the posted snippet.
In other words, I cannot infer what you are trying to do by what you have posted. Please, clarify what you are trying to achieve.

exit; is not necessary.

Thank you, Aia, for posting! Sorry for the confusion...

Here's the program flow which I am seeking to achieve with my crude little snippet:

  1. Begin by printing the word "starting" to the terminal.
  2. Check ~/.somedir using while() to see if the file "testFile" is present.
  3. If it is, send the phrase "file detected" to the terminal; and loop back again to check if "testFile" is still present after a 1-second timeout.
  4. If "testFile" doesn't exist on ~/.somedir, print the phrase "file missing" to the terminal and exit.

Not too exciting; but I think it about encapsulates what I need to do :slight_smile:

To this end, I have formed three different while() statements to interchangeably fit into the main script code:


[*]while (`wc -l ~/.somedir/testFile | sed -e 's/ \/.*$//'` eq "0")
[*]while (`ls -a ~/.somedir | grep -e \"testFile\"` eq "testFile")
[*]while (-e "~/.somedir/testFile")

The commandlines from 1) and 2) both work well as stand-alone code at the terminal; but do not execute properly from Perl. #2 is particularly well-suited to the work; as it doesn't rely upon the file being of any particular size to allow for successful detection. String comparisons should logically work as expected in this context.

Choice #3 is preferred as a straightforward solution; but, unfortunately, Perl will not find our "testFile" on a hidden directory such as ~/.somedir using the normal

while (-e "~/.somedir/testFile")

statement layout.

So, that's the problem in a nutshell...

Again, I'd prefer going with the straight-Perl approach which #3 offers. But, if making this work is more complicated than getting the commandline in

while (`ls -a ~/.somedir | grep -e \"testFile\"` eq "testFile")

to function correctly in this code context, I'll settle for a just "quick fix" of #2 for now.

Thanks again!

That sounds fishy to me as nothing about UNIX except ls cares about hidden files and folders.

You know what? It doesn't work on non-hidden dirs either. It always fails, because ~/ which is a shell feature not a perl one.

Use an absolute path, or substitute HOME a la $ENV{"HOME"}."/folder/file" and -e works fine.

1 Like

There is no problems for Perl using the hidden directories and files, the issue is with ~ . It does not translate to home like in the shell.
Please, try:

while ( -e "$ENV{'HOME'}/.somedir/testFile" )
{
    $| = 1; # to flush the print without the newline
    print " file detected ";
    sleep 1;
}
1 Like

Thank you both so much for the input! The Perl code seems to work well now; and I picked up yet another kernel of savvy :wink:

One last question, if folks have a moment.

Not furnished with network access yesterday afternoon, I fiddled for a while and found out why

while (`ls -a ~/.somedir | grep -e \"testFile\"` eq "testFile")

from the OP didn't work either.

Seems as though an unidentified character is being "automagically" appended to the "testFile" string which is returned to Perl. The following updated line works, but it seems a bit "sloppy" to allow anything aside from a neat eq operation with a string comparison operation like this:

while (`ls -a ~/.somedir | grep -s -e \"testFile\"` ge "testFile")

In the spirit of learning new stuff, is there a way of cleaning up this output with a bit of additional inline instruction to allow something like

while (`ls -a ~/.somedir | grep -s -e \"testFile\"` eq "testFile")

to actually work as anticipated?

So much to learn...

Thanks again; and have a great day :slight_smile:

I get that you are learning or trying to learn. Nevertheless, I question the desire to learn something you will not have any use for it, if you wanted to do it correctly.

Calling two different system programs to pipe them together in order to evaluate the resulted output would be the hallmark of someone that probably needs to do things in a shell and not with Perl. Not considering, that what you are accepting as a valid comparison is not.

Addressing the highlighted red part of the quote: Is it not an `unidentified' character. It's a \n from running the command ls -a

I think some clarification about "hidden files" is in order, because it seems this in first place has lead to the confusion:

"Hidden files" is a concept going back to the MS-DOS ("FAT") file system. There was an attribute in the directory entry marking a file "hiidden" (or not hidden) and all programs processing or creating file lists didn't show files with this attribute set as long as not explicitly told to do so.

There is no such concept at all in place in UNIX filesystems! In fact "ls" by convention does not display file(name)s starting with a "." unless told otherwise by the use of the "-a" switch. Still, this is only "ls" and it makes the files/directories any special at all. The whole mechanism is just to allow for the rc-files, config directories and other things one is "normally" not interested in to be filtered from display when doing an "ls". But that is no attribute inherent to the file, it is just a mechanism inside "ls".

I hope this helps.

bakunin

Thank you, bakunin, for that tidbit. Wasn't sure how to refer to the dot-prefixed file and dir naming convention/scheme apart from how it is dubbed by others out here in the wild; hence the chosen title for my post.

@Aia:
Thanks for letting me know which entity(?) is being passed along to Perl in this particular situation. I'd suspected as much, but was unable to banish the offending code appendage during my learning exercises the other day.

On other points, I have a question for you: Is it better to have more or less information in any particular coding scenario? Sending commands to the system via Perl is an accepted and widespread practice; and one which could be of overall benefit to others at some junctures.

Case in point: a friend of mine is an Electrophysicist of near-retirement age who dabbles in Perl; and only recently discovered the use of backticks in passing along system commands. After our conversation, he was grateful for the information; and began his own digging in that direction. In the context of this microcosm, perfecting one's crossover capabilities in this area of Perl codewriting is, I believe, a worthy undertaking for folks from all walks who may visit here...

That being said, the personal comments in your last post came across, quite frankly, as insular and strident; particularly in light of the forum in which the OP was posted. Some who visit these pages may have to deal with that type of interaction on a regular basis in real life and in potentially serious matters; and come to unix.com to relax, learn, and pursue better things.

At any rate, all the best to you; and many thanks for the valuable contributions which you present in these forums.

Good day, all!

Hi, LinQ

Please, do not misunderstand my point. Using the back ticks and any other facilities that Perl has to make a system call is perfectly acceptable when the need arise (apart from getting abused most of the time). My comment was referring specifically to "your" specific attempt in the while loop you shown. Using ls -a ... | grep ... (eq or ge) something in a while loop is a broken code, it does not work, even if it appears to work to you and the only way to fix it is to not use it.
Sorry, if that's not agreeable to you. Next time, I will try to remember to keep my keyboard as inactive as tits on a boar.