bp4a has asked for the wisdom of the Perl Monks concerning the following question:

I am running the following system command:

df -h | grep /db2/$DB2DBDFT/sapdata

in my script and assigning it to a variable which I then later print to a file and the file is then put in an email.

When I run the command at the prompt I get this:

df -h | grep /db2/$DB2DBDFT/sapdata 30G 26G 2.1G 93% /db2/BXP/sapdata1 30G 11G 18G 37% /db2/BXP/sapdata2 30G 23G 5.9G 80% /db2/BXP/sapdata3 30G 6.0G 23G 22% /db2/BXP/sapdata4 2.0G 36M 1.9G 2% /db2/BXP/sapdatat 2.0G 36M 1.9G 2% /db2/BXP/sapdatat2

When I run the script I get this error:

sh: line 82: printf: `/': invalid format character

The line number is wrong for one thing but that is besides the point. Here is the code:

print OUT "Current File System Usage:\n"; print OUT "Filesystem Size Used Avail Use Mounted on\n"; $rc = `df -h | grep /db2/$DB2DBDFT/sapdata`; print OUT "$rc\n";

I think it has to do with the / in the "filesystem name" column or the "Mounted on" column. The weird thing is that I don't have this problem on Unix.

I appreciate any suggestions on how to handle this.

Replies are listed 'Best First'.
Re: print question
by ikegami (Patriarch) on Jun 02, 2011 at 15:51 UTC

    The error occurs in a printf in a shell script. You did not show any code using printf.

    The only shell script you did show is only one line long (df -h | grep /db2/$DB2DBDFT/sapdata), but the error occurred at line 82 of a shell script.

    What you are showing us is not relevant to the problem at hand.

    That said, I think you do have an error in what you posted. In the first snippet, you use the shell's variable $DB2DBDFT. In the second, you use Perl's variable $DB2DBDFT. If that is a problem, use strict; should catch it once you get your other problems are sorted out.

    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: print question
by toolic (Bishop) on Jun 02, 2011 at 15:53 UTC
    Your error message says printf, but I don't see a printf in the 4 lines of perl code you posted.

    Here is a wild guess. $DB2DBDFT is an environment variable. But, inside your perl code, $DB2DBDFT is just a plain variable which you have not defined. If it is an environment variable, then you should use:

    $rc = `df -h | grep /db2/$ENV{DB2DBDFT}/sapdata`;
    Also, use strict and warnings.
      unshift (@INC, "/db2/$DB2DBDFT/Scripts"); require 'variables.pl'; use Env;

      This is declared at the top of my script, I am telling it to use Environment variables.

      Works fine on Unix

      I think it has to do with the USE% column because in that column there is ##% then it lists the directory. So when it sees the % in the varible $rc followed by the / of the directory it says "Error" you are trying to do printf on a / which cannot be formatted by printf.

      Maybe I should be asking how to do a df command that drops the Use% column but gives me everything else?

        So when it sees the % in the varible $rc followed by the / of the directory it says "Error"

        Nothing you showed looks at what's in $rc except print, and print does not treat % specially. From what you told us, your diagnosis is incorrect.

        You could get that error if the contents of the file you write to is used as a printf format string by something else.

        Maybe I should be asking how to do a df command that drops the Use% column but gives me everything else?
        You could try parsing df output with the CPAN module: Filesys::Df

        Is it possible for you to reduce your code while still producing the same error? If you could post some code that anyone here could run, we might be able to help you debug it better. For example, does this simplified code still give you an error?

        use warnings; use strict; use autodie; open OUT, '> df.out'; my $rc = `df -h`; print OUT "$rc\n";
Re: print question
by flexvault (Monsignor) on Jun 03, 2011 at 12:27 UTC

    Some underlining information about the operating system is needed to explain your problem. When typing the command 'df' on your terminal window, your interface to the operating system is a program called a shell. There are many shell programs ( I prefer the korn shell myself ) and each different shell program has it's own definitions of what sequences are correct.

    Running your perl script under 'unix' or 'linux', your interface to the operating system is 'perl', but how 'perl' is called also matters. When your perl script calls the operating system with 'system', qx//, backticks etc., you can't be sure that perl will get the exact same results as when you typed it on the command line. Most often the results are the same or similar. (Note: This is why others have mentioned the '$', it has to be escaped to get it to the shell. But shell considerations also matter.)

    This is especially true when the perl script is called from 'cron', allowing it to be called on a specific schedule.

    Another approach is too change the shell to the same as your Unix system (if it is available).

    Good Luck

    "Well done is better than well said." - Benjamin Franklin

      Thanks for the explanation! The funny thing is that both OS'es were using the same shell. Its like the Perl motto, more than one way to do it.
Re: print question
by bp4a (Initiate) on Jun 03, 2011 at 14:04 UTC
    Problem SOLVED!!! Evidently there is a difference in how Unix uses the df

    command in csh and how Linux uses the df command in csh. Something to do with the printf.

    Here is the command that works on Linux:

    df -h | grep /db2/$DB2DBDFT/sapdata | sed 's/%/ /g'

    Coworker came up with this solution....