May the source be with you, but remember the KISS principle ;-)

Contents Bulletin Scripting in shell and Perl Network troubleshooting History Humor

Command Line PHP

Old News

PHP as Visual Basic of the Web

Recommended Links

Perl for Unix System Administrators
Pipes -- powerful and elegant programming paradigm Humor Random Findings Etc

 from PHP Using PHP from the command line - Manual

As of version 4.3.0, PHP supports a new SAPI  type (Server Application Programming Interface) named CLI  which means Command Line Interface. As the name implies, this SAPI  type main focus is on developing shell (or desktop as well) applications with PHP.

There are quite a few differences between the CLI SAPI  and other SAPIs which are explained in this chapter. It's worth mentioning that CLI  and CGI  are different SAPI's although they do share many of the same behaviors.

Since PHP 4.3.0 the option --enable-cli  is on by default. You may use --disable-cli  to disable it.

By default when executing make, both the CGI and CLI are built and placed as sapi/cgi/php and sapi/cli/php respectively, in your PHP source directory. You will note that both are named php. What happens during make install  depends on your configure line. If a module SAPI is chosen during configure, such as apxs, or the --disable-cgi  option is used, the CLI is copied to {PREFIX}/bin/php during make install  otherwise the CGI is placed there. So, for example, if --with--apxs is in your configure line then the CLI is copied to {PREFIX}/bin/php during make install. If you want to override the installation of the CGI binary, use make install-cli  after make install. Alternatively you can specify --disable-cgi  in your configure line.

Note: Because both --enable-cli  and --enable-cgi  are enabled by default, simply having --enable-cli  in your configure line does not necessarily mean the CLI will be copied as {PREFIX}/bin/php during make install.

Starting with PHP 4.3.0 the windows package distributes the CLI as php.exe in a separate folder named cli, so cli/php.exe . Starting with PHP 5, the CLI is distributed in the main folder, named php.exe. The CGI version is distributed as php-cgi.exe. As of PHP 5, a new php-win.exe file is distributed. This is equal to the CLI version, except that php-win doesn't output anything and thus provides no console (no "dos box" appears on the screen). This behavior is similar to php-gtk. You should configure with --enable-cli-win32.

What SAPI do I have?: From a shell, typing php -v  will tell you whether php is CGI or CLI. See also the function php_sapi_name() and the constant PHP_SAPI.

Note: A Unix manual page was added in PHP 4.3.2. You may view this by typing man php  in your shell environment.

Differences of the CLI SAPI  compared to other SAPIs:

The list of command line options provided by the PHP binary can be queried anytime by running PHP with the -h  switch:

Usage: php [options] [-f] <file> [--] [args...]
       php [options] -r <code> [--] [args...]
       php [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]
       php [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]
       php [options] -- [args...]
       php [options] -a

  -a               Run interactively
  -c <path>|<file> Look for php.ini file in this directory
  -n               No php.ini file will be used
  -d foo[=bar]     Define INI entry foo with value 'bar'
  -e               Generate extended information for debugger/profiler
  -f <file>        Parse <file>.
  -h               This help
  -i               PHP information
  -l               Syntax check only (lint)
  -m               Show compiled in modules
  -r <code>        Run PHP <code> without using script tags <?..?>
  -B <begin_code>  Run PHP <begin_code> before processing input lines
  -R <code>        Run PHP <code> for every input line
  -F <file>        Parse and execute <file> for every input line
  -E <end_code>    Run PHP <end_code> after processing all input lines
  -H               Hide any passed arguments from external tools.
  -s               Display colour syntax highlighted source.
  -v               Version number
  -w               Display source with stripped comments and whitespace.
  -z <file>        Load Zend extension <file>.

  args...          Arguments passed to script. Use -- args when first argument
                   starts with - or script is read from stdin

The CLI SAPI  has three different ways of getting the PHP code you want to execute:

  1. Telling PHP to execute a certain file.
    php my_script.php
    php -f my_script.php
    Both ways (whether using the -f  switch or not) execute the file my_script.php. You can choose any file to execute - your PHP scripts do not have to end with the .php  extension but can have any name or extension you wish. 

  2. Pass the PHP code to execute directly on the command line.
    php -r 'print_r(get_defined_constants());'
    Special care has to be taken in regards of shell variable substitution and quoting usage. 

    Note: Read the example carefully, there are no beginning or ending tags! The -r  switch simply does not need them. Using them will lead to a parser error.

  3. Provide the PHP code to execute via standard input (stdin).

    This gives the powerful ability to dynamically create PHP code and feed it to the binary, as shown in this (fictional) example:

    $ some_application | some_filter | php | sort -u >final_output.txt
You cannot combine any of the three ways to execute code.

Like every shell application, the PHP binary accepts a number of arguments but your PHP script can also receive arguments. The number of arguments which can be passed to your script is not limited by PHP (the shell has a certain size limit in the number of characters which can be passed; usually you won't hit this limit). The arguments passed to your script are available in the global array $argv. The zero index always contains the script name (which is -  in case the PHP code is coming from either standard input or from the command line switch -r). The second registered global variable is $argc  which contains the number of elements in the $argv  array (not the number of arguments passed to the script).

As long as the arguments you want to pass to your script do not start with the -  character, there's nothing special to watch out for. Passing an argument to your script which starts with a -  will cause trouble because PHP itself thinks it has to handle it. To prevent this, use the argument list separator --. After this separator has been parsed by PHP, every argument following it is passed untouched to your script.

# This will not execute the given code but will show the PHP usage
$ php -r 'var_dump($argv);' -h
Usage: php [options] [-f] <file> [args...]

# This will pass the '-h' argument to your script and prevent PHP from showing it's usage
$ php -r 'var_dump($argv);' -- -h
array(2) {
  string(1) "-"
  string(2) "-h"

However, there's another way of using PHP for shell scripting. You can write a script where the first line starts with #!/usr/bin/php. Following this you can place normal PHP code included within the PHP starting and end tags. Once you have set the execution attributes of the file appropriately (e.g. chmod +x test) your script can be executed like a normal shell or perl script:

Assuming this file is named test in the current directory, we can now do the following:
$ chmod +x test
$ ./test -h -- foo
array(4) {
  string(6) "./test"
  string(2) "-h"
  string(2) "--"
  string(3) "foo"
As you see, in this case no care needs to be taken when passing parameters which start with -  to your script. 

Long options are available since PHP 4.3.3.

Option Long Option Description
-a --interactive Runs PHP interactively. If you compile PHP with the Readline extension (which is not available on windows), you'll have a nice shell, including a completion feature (e.g. you can start typing a variable name, hit the TAB key and PHP completes its name) and a typing history that can be accessed using the arrow keys. The history is saved in the ~/.php_history file.

Note: Files included through auto_prepend_file and auto_append_file are parsed in this mode but with some restrictions - e.g. functions have to be defined before called.

-c --php-ini With this option one can either specify a directory where to look for php.ini or you can specify a custom INI  file directly (which does not need to be named php.ini), e.g.:
$ php -c /custom/directory/ my_script.php

$ php -c /custom/directory/custom-file.ini my_script.php
If you don't specify this option, file is searched in default locations
-n --no-php-ini Ignore php.ini at all. This switch is available since PHP 4.3.0.
-d --define This option allows you to set a custom value for any of the configuration directives allowed in php.ini. The syntax is:
-d configuration_directive[=value]

Examples (lines are wrapped for layout reasons):

# Omitting the value part will set the given configuration directive to "1"
$ php -d max_execution_time
        -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(1) "1"

# Passing an empty value part will set the configuration directive to ""
php -d max_execution_time=
        -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(0) ""

# The configuration directive will be set to anything passed after the '=' character
$  php -d max_execution_time=20
        -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(2) "20"
$  php
        -d max_execution_time=doesntmakesense
        -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(15) "doesntmakesense"
-e --profile-info Activate the extended information mode, to be used by a debugger/profiler.
-f --file Parses and executed the given filename to the -f  option. This switch is optional and can be left out. Only providing the filename to execute is sufficient.
-h and -? --help and --usage With this option, you can get information about the actual list of command line options and some one line descriptions about what they do.
-i --info This command line option calls phpinfo(), and prints out the results. If PHP is not working correctly, it is advisable to use php -i  and see whether any error messages are printed out before or in place of the information tables. Beware that when using the CGI mode the output is in HTML  and therefore quite huge.
-l --syntax-check This option provides a convenient way to only perform a syntax check on the given PHP code. On success, the text No syntax errors detected in <filename>  is written to standard output and the shell return code is 0. On failure, the text Errors parsing <filename>  in addition to the internal parser error message is written to standard output and the shell return code is set to 255.

This option won't find fatal errors (like undefined functions). Use -f  if you would like to test for fatal errors too.

Note: This option does not work together with the -r  option.

-m --modules Using this option, PHP prints out the built in (and loaded) PHP and Zend modules:
$ php -m
[PHP Modules]

[Zend Modules]
-r --run This option allows execution of PHP right from within the command line. The PHP start and end tags (<?php  and ?>) are not needed and will cause a parser error if present.

Note: Care has to be taken when using this form of PHP to not collide with command line variable substitution done by the shell.

Example showing a parser error

$ php -r "$foo = get_defined_constants();"
Command line code(1) : Parse error - parse error, unexpected '='
The problem here is that the sh/bash performs variable substitution even when using double quotes ". Since the variable $foo  is unlikely to be defined, it expands to nothing which results in the code passed to PHP for execution actually reading:
$ php -r " = get_defined_constants();"
The correct way would be to use single quotes '. Variables in single-quoted strings are not expanded by sh/bash.
$ php -r '$foo = get_defined_constants(); var_dump($foo);'
array(370) {
If you are using a shell different from sh/bash, you might experience further issues. Feel free to open a bug report at One can still easily run into troubles when trying to get shell variables into the code or using backslashes for escaping. You've been warned. 

Note: -r  is available in the CLI SAPI and not in the CGI SAPI.

Note: This option is meant for a very basic stuff. Thus some configuration directives (e.g. auto_prepend_file and auto_append_file) are ignored in this mode.

-B --process-begin PHP code to execute before processing stdin. Added in PHP 5.
-R --process-code PHP code to execute for every input line. Added in PHP 5.

There are two special variables available in this mode: $argn  and $argi. $argn  will contain the line PHP is processing at that moment, while $argi  will contain the line number.

-F --process-file PHP file to execute for every input line. Added in PHP 5.
-E --process-end PHP code to execute after processing the input. Added in PHP 5.

Example of using -B, -R  and -E  options to count the number of lines of a project.

$ find my_proj | php -B '$l=0;' -R '$l += count(@file($argn));' -E 'echo "Total Lines: $l\n";'
Total Lines: 37328

-s --syntax-highlight and --syntax-highlight Display colour syntax highlighted source.

This option uses the internal mechanism to parse the file and produces a HTML  highlighted version of it and writes it to standard output. Note that all it does it to generate a block of <code> [...] </code>  HTML  tags, no HTML  headers.

Note: This option does not work together with the -r  option.

-v --version Writes the PHP, PHP SAPI, and Zend version to standard output, e.g.
$ php -v
PHP 4.3.0 (cli), Copyright (c) 1997-2002 The PHP Group
Zend Engine v1.3.0, Copyright (c) 1998-2002 Zend Technologies
-w --strip Display source with stripped comments and whitespace.

Note: This option does not work together with the -r  option.

-z --zend-extension Load Zend extension. If only a filename is given, PHP tries to load this extension from the current default library path on your system (usually specified /etc/ on Linux systems). Passing a filename with an absolute path information will not use the systems library search path. A relative filename with a directory information will tell PHP only to try to load the extension relative to the current directory.

The PHP executable can be used to run PHP scripts absolutely independent from the web server. If you are on a Unix system, you should add a special first line to your PHP script, and make it executable, so the system will know, what program should run the script. On a Windows platform you can associate php.exe with the double click option of the .php  files, or you can make a batch file to run the script through PHP. The first line added to the script to work on Unix won't hurt on Windows, so you can write cross platform programs this way. A simple example of writing a command line PHP program can be found below.

Example 43-1. Script intended to be run from command line (script.php)


if ($argc != 2 || in_array($argv[1], array('--help', '-help', '-h', '-?'))) {

This is a command line PHP script with one option.

  <?php echo $argv[0]; ?> <option>

  <option> can be some word you would like
  to print out. With the --help, -help, -h,
  or -? options, you can get this help.

} else {
   echo $argv[1];

In the script above, we used the special first line to indicate that this file should be run by PHP. We work with a CLI version here, so there will be no HTTP header printouts. There are two variables you can use while writing command line applications with PHP: $argc  and $argv. The first is the number of arguments plus one (the name of the script running). The second is an array containing the arguments, starting with the script name as number zero ($argv[0]).

In the program above we checked if there are less or more than one arguments. Also if the argument was --help, -help, -h  or -?, we printed out the help message, printing the script name dynamically. If we received some other argument we echoed that out.

If you would like to run the above script on Unix, you need to make it executable, and simply call it as script.php echothis  or script.php -h. On Windows, you can make a batch file for this task:

@C:\php\php.exe script.php %1 %2 %3 %4

Assuming you named the above program script.php, and you have your CLI php.exe in C:\php\php.exe this batch file will run it for you with your added options: script.bat echothis  or script.bat -h.

See also the Readline extension documentation for more functions you can use to enhance your command line applications in PHP.

Top updates

Softpanorama Switchboard
Softpanorama Search


Old News ;-)

[Jul 10, 2006] International PHP Magazine Featured ArticlePHP CLI Unveiled!

In the weird and wonderful world of scripting languages, no languages demand more respect than those listed under the letter P in the scripter’s dictionary. For years system administrators have relied on these distinguished scripting languages to do everything from trivial computer maintenance tasks to providing backends to mission critical systems. Perl and Python have served us well, but while their pundits do battle for supremacy in the command line arena, PHP has been gathering its forces.

Quietly and with little ado, PHP 5 has brought the power and strengths of PHP to the command line, making PHP a tool of choice for Web developers and system administrators alike.

[Nov 27, 2002] Some Thoughts on PHP

Author:   John Lim    
Posted: 11/27/2002; 9:37:30 AM
Topic: Some Thoughts on PHP
Msg #: 2082 (top msg in thread)
Prev/Next: 2078/2085
Reads: 8413

Some Thoughts on PHP  I just received this interesting email from Derek Comartin. I thought I would share his message and my response with you.


I have been reading PHPEverywhere ever since I found it about a year back. I love reading it and your thoughts about the latest tech. Just recently I started using ADOdb for a project and love it. I am not a huge fan of PEAR's DB or PEAR in general (although I am using its SOAP package).

Anyways, the real point of my e-mail is that I am really getting frustrated with PHP. I have been developing applications with PHP for 3 years now, mainly developing intranet and CMS the like. My problem is that it seems like PHP is close to what I want it todo, but not quite. I would like to hear your thoughts and the thoughts of other php developers (people that use it everyday).

Let me say first of all I have absolutely no influence on the direction of PHP. I do not have CVS access to the PHP source code, and wouldn't have the time to contribute even if I wanted to. However some people might be interested in my opinion.

To me PHP is a pragmatic language. It is not based on any formal theory nor specification. It grew the same way as Perl, due to demand from skilled hackers. However Rasmus Lerdorf and company seem to be more keen on pruning the core language than the Perl gods and keeping it really simple. For example, to me the lack of the more advanced OOP features is a blessing. I was never impressed with C++ and its complexity, although I coded in it nearly every working day for 5 years.

(BTW, sorry if this is going to get long.. my real goal here is maybe you can post this on your site and hope to get some feedback in your comments section).

1) Templates Almost everyone agrees that mixing HTML and PHP is a bad idea. Personally I have developed my own template library that is simple and thin. Since PHP is geared toward web applications why in gods name don't they develop a SIMPLE template library built-into PHP. I cannot understand for 1 minute the point of smarty? I do think smarty is a very well designed library but I don't understand the point of making a library that introduces more business logic. Isn't the point of a template to seperate buisiness logic from UI? Who is coming up with this stuff?

The development of templates was an attempt to fight against complexity. This is good. Yes PHP is a template-based language, but that doesn't mean that good techniques preclude more advanced strategies for separating code,data and presentation. For very big scripts, we split code into functions and into several include files. We store data in an RDBMS for better management. So for very big web pages, it makes sense to split it into multiple files, and split presentation to template files too. Then we have a N-layer architecture of:


From a theoretical point of view, perhaps Smarty has gone too far. Smarty does not merely deal with presentation issues, but has a full-blown programming language built-in. There is always the temptation to add functionality to something that began as a simple project. In some ways, Smarty compiled code is obfusticated PHP :-)

However from a commercial perspective, Smarty is cool. I can release a Zend encoded PHP product, and provide customization features by basing my user interface on Smarty, which the client can modify and even script without touching my compiled code.

So it really depends on your perspective. One man's Toyota is another man's Rolls Royce. And some people refuse to learn to drive and will never see the point of using Smarty.

(BTW: I have been wondering if someone has written a template library that is something like this:

If you had a template that had a <form id="myForm"> tag, then in your PHP you could modify tag properties etc... im not sure if does something like this.. so your code would be:


Kinda like how Javascript can minipulate objects, you could do with any HTML tag.. ie: forms, tables, yadda yadda

There are several libraries that do this already if you search on including (wink-wink) my company's product, phpLens which goes one step further in providing graphical ui designers/wizards. And my point of view is a little bit more radical - doing this without graphical aids is a step backward. For example this doesn't excite me:


because you lose the benefits of a graphical tool like dreamweaver that recognizes input tags for the obscure benefit of coding everything as objects. Half the power of MS.NET is the graphical tools of Visual Studio.NET.

Note that I had to use $size and $maxlength before you could even guess what the parameters of the function were. The beauty of HTML is that it is self-documenting.

2) Database

Thanks to you I use a great database abstraction. But why on earth isnt there abstraction built-in? I still like having functions for a specific API, but there should be db abstraction on top of that built in for speed.

Anyways these are just my random thoughts... I love PHP but there are too many things that are beginning to piss me off (did I also mention nonsense like how functions like explode, strstr have there haystack/needle arguments in different orders? Shouldnt this be common across all functions.... ah the little things.)

What are your thoughts?

PHP was developed to meet a need. PHP has grown organically, not because it was sponsored by big companies like Sun or IBM (eg java). People originally used PHP to create web-sites where the database was probably known; in contrast, database abstraction is only required if you are creating web applications that can be installed in different environments. I rarely do web-sites, most of my PHP work is for web-applications that run on Intranets/Extranets. That's how ADOdb came about. That's how PHP came about - to meet an immediate need.

So as PHP has matured, so has the needs become more sophisticated. Some people will always want PHP to do more and grow in more powerful ways (data abstraction, 100% OOP, etc), but as PHP growth is organic, you have to wait till someone faces the problem and comes up with the solution and post it to the net. This laissez-faire approach works because the number of PHP developers has reached a critical mass (perhaps when PHP4 was released).

Of course some things could have been better planned from the beginning of PHP, but no one would have started work till the last bit of the plan was nailed solid, which would have taken too long. Instead Zeev and Andi (and Rasmus?) are still very conservative about the core language, and they let you and me build whatever we like without comment. PHP-Nuke and Post-Nuke might never have been developed if Rasmus had blessed Midgard as the way to go. Of course there are people who say that the Nuke forks cannot compare to Zope or Soup or Whatever, or that the PHP api is not as nice as Java's or Python's -- but that misses the point. Millions of people are using and benefiting from the free software when programming in Java or Python or C# would have been too difficult. And this gives impetus for people to create better software.

-- John Lim - Introduction to PHP5

PHP5 is not yet official but the development versions are already usable (and unstable!) so we can start to learn and practice the new features of the upcoming version of PHP. In this article I will focus in three major new features of PHP5:.

* The new object model
* Exceptions
* Namespaces

First of all a couple of disclaimers:

* Some of the techniques described in this article can be done with PHP4, but are presented anyway to make the whole article more readable.
* Some of the features described in this article may change in the final release of PHP5.

PHP5 has not been released yet and I don't know when that will be but you can already try and investigate the new features of the language by downloading and installing a PHP5 development version from There you will find Linux and Windows versions of PHP5 ready to be used. Installation proceeds as in any normal PHP distribution so go there and grab a brand new toy.


Message # 1016053:
Date: 04/12/03 07:01
By: Marcel Swinkels
Subject: Oh my god!

If this is the future for PHP why not start using JSP? :-(


Message # 1016064:
Date: 04/13/03 11:28
By: John C. Ghormley Profile
Subject: Look like Java to me

As an old time procedural coder, I didn't continue to pursue Java simply because I can't seem to get my mind around the OO paradigm when trying to think through a problem. So PHP was a great solution. Very procedural even if not politically correct for the times. Now, it seems the powers of PHP want to make it OO. That causes me a bit of concern and the concerns are these:
1) We're adding a lot of code overhead into the PHP code base to support OO.
2) Will that additional overhead slow the response time of PHP significantly?
3) If it does, how soon will the procedural elements begin to be extracted in favor of a more politically acceptable OO?
4) Assuming there is not degradation in performance, how soon will the pressure to conform to more politically acceptable practices cause the procedural elements to disappear?

On first read, I think i'd concur with Swinkels -- why not switch to JSP?
Message # 1016192:
Date: 04/20/03 17:24
By: Scott R.S.
Subject: RE: Look like Java to me

PHP CURRENTLY (4.3.x) outruns any JAVA code and 99% of the latest .NET stuff from Microsoft/MajorGreedy!!! Mind you I spent YEARS as a die hard MS guru building major systems for investment and retail banks as well as insurance, medical and communications sectors using MS tools. I looked at moving to Java and being something of a purist found all the OOP crap (forgive me folks) to be much ado about nothing that simply adds significant amounts of time and thus expense to projects without being able to support the speed and stability enterprise customers demand. Further while Java is somewhat portable, it still has light years to go before it can compete with .NET in terms of speed... I kept looking, and then, the BEST OF BREED, PHP!!!! Portable, powerful, FAST when it's free and when you compile it, get out of the way!!!!!!!! What a piece of software!!!! Take a look at for some compiled PHP in action, be sure to notice the transaction timer in the lower left corner of results, then keep in mind the database has 1.7 million rows in it right now. Let's see MS or Java do that in under a second, oh that's right, THEY CAN'T!!!! The math ALONE is too much for either to support at any speed, then factor in the amount of data involved and neither can hope to touch it... I know, I was CTO of a startup that TRIED to build something for insurance companies in WINDOWS and WITHOUT any math, and only a couple hundred thousand records CHOKED and locked up the server... Want REAL power, and speed (which is simply defined as "power in excess of a given task") then build in PHP and compile it!!!! Compiling PHP is now SO MUCH more affordable with the Small business program from http://ZEND.COM that it pays to compile!!!!

Message # 1016118:
Date: 04/15/03 08:39
By: Zeev Suraski
Subject: PHP's direction - reassurance

Just to reassure the people here that don't want to see PHP becoming an OO language - have no worries, this is not going to happen.

We've definitely added lots of OO features to the Zend Engine 2, but all of the structured code features remain intact. PHP's built-in functions are and will remain procedural. I think Jean-Marc hit it well - we want to give authors of larger-scale projects, or those that buy into the OO model, the tools to write their apps better. They've been using OO in PHP 4, but were bumping into all sorts of problems and limitations. We have no plan or will to try and encourage people to move away from procedural programming if they're happy with it.
Message # 1016603:
Date: 05/29/03 01:36
By: Excorcist
Subject: This is so stupid

I can't believe this

In PHP4 as you may already know variables are passed to functions/methods by value (a copy is passed) unless you use the '&' symbol in the function declaration indicating that the variable will be passed as a reference. In PHP5 objects will be passed always as references. Object assignation is also done by reference.

WTF is that crap??? You're trying to rip php out of it's roots and make it some kind of psuedo java. WHat the hell? If this isn't a step backwards I don't know what is. My god I can't believe this.
Message # 1016746:
Date: 06/16/03 04:34
By: Zeev Suraski
Subject: RE: This is so stupid

You should be thankful, then, that you'd be able to enable compatibility mode and have your objects behave in the same way as previous versions of PHP have, and be passed by value.

If you consider the old behavior an advantage, in any way, then I believe you've never written an OO piece of code. That's fine, by the way - as PHP 5 will definitely not force you to write OO, it'll just make it a heck of a lot easier.
Message # 1016750:
Date: 06/16/03 10:16
By: David Fells
Subject: I guess IL is next...

Seems like the php team is on the right track with finally giving try/catch exception handling and providing access modifier keywords for class members. I'm just not really convinced of the necessity in using OOP in php...

In some tests I ran recently before deciding whether to completely rebuild or just reuse some old code someone else wrote for a new project, the OOP code they wrote ran approximately 10 times more slowly than the procedural code I wrote... by simply putting what would be a "class" in it's own include file and including as needed, you still have the basic reusability of OOP without the extra compile/execute time of objects.

I'm just afraid the addition of namespaces, exception catching, catchalls, and access modifiers are only going to make the performance of OOP in PHP get worse =( I just hope they don't choose to go to an IL/JIT model to compensate ! Yuck.
Message # 1016549:
Date: 05/21/03 19:27
By: Brandon Goodin
Subject: RE: Look like Java to me

Let me preface by saying.. 'to each their own'.

Having been a long time Java programmer and currently still, I find that many of the comments that have been made in this thread regarding java are outdated and even innacurate.

I don't have the time to go back and speak on each point specifically. But, from a personal standpoint Java has been progessing as fast and furious as other technologies (including php). Short comings from 2 years ago don't apply to today.

To state some positives about Java:
- Object generation and garbage collection has improved drastically.
- Various open-source and commercial frameworks have emerged to allow for quick and efficient assembly of applications (client and server). Most use good OO design patterns.
- Because of the decoupling of various layers of the application better code management is possible. (i.e View/Controller/Logic/Data Layer/Web Services)

I encourage you all to post your statements to a Java discussion board and see what responses you get. You might learn something about Java that you didn't know.

Personally, I like php. It's a great language... for the web and for small-midsize to small jobs. I got away from the page scripting as a mainstay because it became to difficult to manage in a team environment. All of the dependencies on the view passing the right parameters to the next page and the tight coupling with the data layer in the end makes things too complex. I use good php coding standards. But, it still doesn't compete with a well formed Java envrionment. Once the job gets to a certain size I find that I can create in Java a lot faster.

I think the direction that php is going with it's Java/C# OOP look and feel is a good thing. But, even with php5 it appears it has a ways to go before it's competing with the maturity of Java/C#/Python type OOP languages. BTW for all the complaining against OOP I find it humorous that php is adopting the very principals you dislike. Procedural will always be around. But in the economy of scale (IMHO) OOP wins.

So, long live PHP OOP!!! :-))

Recommended Links

PHP: Using PHP from the command line - Manual

PHP CLI and Cron

RPM resource php-cli

Random Findings

add a note add a note User Contributed Notes
Using PHP from the command line

16-Sep-2006 12:05

It seems like 'max_execution_time' doesn't work on CLI.

php -d max_execution_time=20
       -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
will print string(2) "20", but if you'l run infinity while: while(true) for example, it wouldn't stop after 20 seconds.
Testes on Linux Gentoo, PHP 5.1.6.
15-Sep-2006 04:59

On windows, you can simulate a cls by echoing out just \r.  This will keep the cursor on the same line and overwrite what was on the line.

for example:

   echo "Starting Iteration" . "\n\r";
   for ($i=0;$i<10000;$i++) {
       echo "\r" . $i;
   echo "Ending Iteration" . "\n\r";

goalain eat gmail dont com
21-Aug-2006 01:20

If your php script doesn't run with shebang (#!/usr/bin/php),
and it issues the beautifull and informative error message:
"Command not found."  just dos2unix yourscript.php
et voila.

If your php script doesn't run with shebang (#/usr/bin/php),
and it issues the beautifull and informative message:
"Invalid null command." it's probably because the "!" is missing in the the shebang line (like what's above) or something else in that area.


stromdotcom at hotmail dot com
21-Feb-2006 11:27

Spawning php-win.exe as a child process to handle scripting in Windows applications has a few quirks (all having to do with pipes between Windows apps and console apps).

To do this in C++:

// We will run php.exe as a child process after creating
// two pipes and attaching them to stdin and stdout
// of the child process
// Define sa struct such that child inherits our handles

sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;

// Create the handles for our two pipes (two handles per pipe, one for each end)
// We will have one pipe for stdin, and one for stdout, each with a READ and WRITE end
HANDLE hStdoutRd, hStdoutWr, hStdinRd, hStdinWr;

// Now create the pipes, and make them inheritable
CreatePipe (&hStdoutRd, &hStdoutWr, &sa, 0))
SetHandleInformation(hStdoutRd, HANDLE_FLAG_INHERIT, 0);
CreatePipe (&hStdinRd, &hStdinWr, &sa, 0)
SetHandleInformation(hStdinWr, HANDLE_FLAG_INHERIT, 0);

// Now we have two pipes, we can create the process
// First, fill out the usage structs
si.hStdOutput = hStdoutWr;
si.hStdInput  = hStdinRd;

// And finally, create the process
CreateProcess (NULL, "c:\\php\\php-win.exe", NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);

// Close the handles we aren't using

// Now that we have the process running, we can start pushing PHP at it
WriteFile(hStdinWr, "<?php echo 'test'; ?>", 9, &dwWritten, NULL);

// When we're done writing to stdin, we close that pipe

// Reading from stdout is only slightly more complicated
int i;

std::string processed("");
char buf[128];

while ( (ReadFile(hStdoutRd, buf, 128, &dwRead, NULL) && (dwRead != 0)) ) {
   for (i = 0; i < dwRead; i++)
       processed += buf[i];

// Done reading, so close this handle too

A full implementation (implemented as a C++ class) is available at

drewish at katherinehouse dot com
25-Sep-2005 01:08

When you're writing one line php scripts remember that 'php://stdin' is your friend. Here's a simple program I use to format PHP code for inclusion on my blog:

  cat test.php | php -r "print htmlentities(file_get_contents('php://stdin'));"

  type test.php | php -r "print htmlentities(file_get_contents('php://stdin'));"

OverFlow636 at gmail dot com
19-Sep-2005 01:27

I needed this, you proly wont tho.
puts the exicution args into $_GET
if ($argv)
   for ($i=1;$i<count($argv);$i++)
       $it = split("=",$argv[$i]);
       $_GET[$it[0]] = $it[1];

php at schabdach dot de
16-Sep-2005 10:06

To pass more than 9 arguments to your php-script on Windows, you can use the 'shift'-command in a batch file. After using 'shift', %1 becomes %0, %2 becomes %1 and so on - so you can fetch argument 10 etc.

Here's an example - hopefully ready-to-use - batch file:

@echo off

set args=

if "%0"=="" goto :finish_arg
set args=%args% %0
goto :get_arg

set php=C:\path\to\php.exe
set ini=C:\path\to\php.ini
%php% -c %ini% foo.php %args%

Usage on commandline:
foo -1 -2 -3 -4 -5 -6 -7 -8 -9 -foo -bar

A print_r($argv) will give you all of the passed arguments.

Lasse Johansson
18-Aug-2005 02:53

Hi, parsing the commandline (argv) can be very simple in PHP.
If you use keyword parms like:

script.php parm1=value parm3=value

All you have to do in script.php is:

for ($i=1; $i < $argc; $i++) {parse_str($argv[$i]);}
$startup=compact('parm1', 'parm2', 'parm3');

14-Jul-2005 06:44

dunno if this is on linux the same but on windows evertime
you send somthing to the console screen php is waiting for
the console to return. therefor if you send a lot of small
short amounts of text, the console is starting to be using
more cpu-cycles then php and thus slowing the script.

take a look at this sheme:
cpu-cycle:1 ->php: print("a");
cpu-cycle:2 ->cmd: output("a");
cpu-cycle:3 ->php: print("b");
cpu-cycle:4 ->cmd: output("b");
cpu-cycle:5 ->php: print("c");
cpu-cycle:6 ->cmd: output("c");
cpu-cylce:7 ->php: print("d");
cpu-cycle:8 ->cmd: output("d");
cpu-cylce:9 ->php: print("e");
cpu-cycle:0 ->cmd: output("e");

on the screen just appears "abcde". but if you write
your script this way it will be far more faster:
cpu-cycle:1 ->php: ob_start();
cpu-cycle:2 ->php: print("abc");
cpu-cycle:3 ->php: print("de");
cpu-cycle:4 ->php: $data = ob_get_contents();
cpu-cycle:5 ->php: ob_end_clean();
cpu-cycle:6 ->php: print($data);
cpu-cycle:7 ->cmd: output("abcde");

now this is just a small example but if you are writing an
app that is outputting a lot to the console, i.e. a text
based screen with frequent updates, then its much better
to first cach all output, and output is as one big chunk of
text instead of one char a the time.

ouput buffering is ideal for this. in my script i outputted
almost 4000chars of info and just by caching it first, it
speeded up by almost 400% and dropped cpu-usage.

because what is being displayed doesn't matter, be it 2
chars or 40.0000 chars, just the call to output takes a
great deal of time. remeber that.

maybe someone can test if this is the same on unix-based
systems. it seems that the STDOUT stream just waits for
the console to report ready, before continueing execution.

24-Jun-2005 09:07

For windows clearing the screen using "system('cls');" does not work (at least for me)...

Although this is not pretty it works... Simply send 24 newlines after the output (for one line of output, 23 for two, etc

Here is a sample function and usage:

   function CLS($lines){  // $lines = number of lines of output to keep
       for($i=24;$i>=$lines;$i--) @$return.="\n";
       return $return;
   fwrite(STDOUT,"Still Processing: Total Time ".$i." Minutes so far..." . CLS(1));

Hope This Helps,

linus at flowingcreativity dot net
30-May-2005 08:32

If you are using Windows XP (I think this works on 2000, too) and you want to be able to right-click a .php file and run it from the command line, follow these steps:

1. Run regedit.exe and *back up the registry.*
2. Open HKEY_CLASSES_ROOT and find the ".php" key.

3. Look at the "(Default)" value inside it and find the key in HKEY_CLASSES_ROOT with that name.
4. Open the "shell" key inside that key. Skip to 8.

5. Add a ".php" key and set the "(Default)" value inside it to something like "phpscriptfile".
6. Create another key in HKEY_CLASSES_ROOT called "phpscriptfile" or whatever you chose.
7. Create a key inside that one called "shell".

8. Create a key inside that one called "run".
9. Set the "(Default)" value inside "run" to whatever you want the menu option to be (e.g. "Run").
10. Create a key inside "run" called "command".
11. Set the "(Default)" value inside "command" to:

cmd.exe /k C:\php\php.exe "%1"

Make sure the path to PHP is appropriate for your installation. Why not just run it with php.exe directly? Because you (presumably) want the console window to remain open after the script ends.

You don't need to set up a webserver for this to work. I downloaded PHP just so I could run scripts on my computer. Hope this is useful!

roberto dot dimas at gmail dot com
26-May-2005 02:52

One of the things I like about perl and vbscripts, is the fact that I can name a file e.g. '' and just have to type 'test, without the .pl extension' on the windows command line and the command processor knows that it is a perl file and executes it using the perl command interpreter.

I did the same with the file extension .php3 (I will use php3 exclusivelly for command line php scripts, I'm doing this because my text editor VIM 6.3 already has the correct syntax highlighting for .php3 files ).

I modified the PATHEXT environment variable in Windows XP, from the " 'system' control panel applet->'Advanced' tab->'Environment Variables' button-> 'System variables' text area".

Then from control panel "Folder Options" applet-> 'File Types' tab, I added a new file extention (php3), using the button 'New'  and typing php3 in the window that pops up.

Then in the 'Details for php3 extention' area I used the 'Change' button to look for the Php.exe executable so that the php3 file extentions are associated with the php executable.

You have to modify also the 'PATH' environment variable, pointing to the folder where the php executable is installed

Hope this is useful to somebody

diego dot rodrigues at poli dot usp dot br
02-May-2005 09:29

#!/usr/bin/php -q
* Simple argv[] parser for CLI scripts
* Diego Mendes Rodrigues - S㯠Paulo - Brazil
* diego.m.rodrigues [at] gmail [dot] com
* May/2005

class arg_parser {
   var $argc;
   var $argv;
   var $parsed;
   var $force_this;

   function arg_parser($force_this="") {
       global $argc, $argv;
       $this->argc = $argc;
       $this->argv = $argv;
       $this->parsed = array();
                           array($this->argv[0]) );

       if ( !empty($force_this) )
           if ( is_array($force_this) )
               $this->force_this = $force_this;

       //Sending parameters to $parsed
       if ( $this->argc > 1 ) {
           for($i=1 ; $i< $this->argc ; $i++) {
               //We only have passed -xxxx
               if ( substr($this->argv[$i],0,1) == "-" ) {
                   //Se temos -xxxx xxxx
                   if ( $this->argc > ($i+1) ) {
                       if ( substr($this->argv[$i+1],0,1) != "-" ) {
                                   $this->argv[$i+1]) );
               //We have passed -xxxxx1 xxxxx2
                                                 array($this->argv[$i]) );

               //Testing if all necessary parameters have been passed

   //Testing if one parameter have benn passed
   function passed($argumento) {
       for($i=0 ; $i< $this->argc ; $i++)
           if ( $this->parsed[$i][0] == $argumento )
               return $i;
       return 0;

   //Testing if you have passed a estra argument, -xxxx1 xxxxx2
   function full_passed($argumento) {
       $findArg = $this->passed($argumento);
       if ( $findArg )
           if ( count($this->parsed[$findArg] ) > 1 )
               return $findArg;
       return 0;

       //Returns  xxxxx2 at a " -xxxx1 xxxxx2" call
   function get_full_passed($argumento) {
               $findArg = $this->full_passed($argumento);

               if ( $findArg )
                   return $this->parsed[$findArg][1];

   //Necessary parameters to script
   function force() {
       if ( is_array( $this->force_this ) ) {
           for($i=0 ; $i< count($this->force_this) ; $i++) {
               if ( $this->force_this[$i][1] == "SIMPLE"
                     && !$this->passed($this->force_this[$i][0])
                   die("\n\nMissing " . $this->force_this[$i][0] . "\n\n");

                               if ( $this->force_this[$i][1] == "FULL"
                                     && !$this->full_passed($this->force_this[$i][0])
                                       die("\n\nMissing " . $this->force_this[$i][0] ." <arg>\n\n");

$forcar = array(
       array("-name", "FULL"),
       array("-email","SIMPLE") );

$parser = new arg_parser($forcar);

if ( $parser->passed("-show") )
   echo "\nGoing...:";

echo "\nName: " . $parser->get_full_passed("-name");

if ( $parser->full_passed("-email") ) 
   echo "\nEmail: " . $parser->get_full_passed("-email");
       echo "\nEmail: default";

if ( $parser->full_passed("-copy") )
       echo "\nCopy To: " . $parser->get_full_passed("-copy");

echo "\n\n";

[diego@Homer diego]$ ./en_arg_parser.php -name -email cool -copy Ana

Missing -name <arg>

[diego@Homer diego]$ ./en_arg_parser.php -name diego -email cool -copy Ana

Name: diego
Email: cool
Copy To: Ana

[diego@Homer diego]$ ./en_arg_parser.php -name diego -email  -copy Ana

Name: diego
Email: default
Copy To: Ana

[diego@Homer diego]$ ./en_arg_parser.php -name diego -email

Name: diego
Email: default

[diego@Homer diego]$

25-Apr-2005 02:28

In a bid to save time out of lives when calling up php from the Command Line on Mac OS X.

I just wasted hours on this. Having written a routine which used the MCRYPT library, and tested it via a browser, I then set up a crontab to run the script from the command line every hour (to do automated backups from mysql using mysqldump, encrypt them using mcrypt, then email them and ftp them off to remote locations).

Everything worked fine from the browser, but failed every time from the cron task with "Call to undefined function: mcrypt [whatever]".

Only after much searching do I realise that the CGI and CLI versions are differently compiled, and have different modules attached (I'm using the install for Mac OS-X, php v4.3.2 and mysql v4.0.18).

I still can not find a way to resolve the problem, so I have decided instead to remove the script from the SSL side of the server, and run it using a crontab with CURL to localhost or in order that it will run through Apache's php module.

Just thought this might help some other people tearing their hair out. If anyone knows a quick fix to add the mcrypt module onto the CLI php without any tricky re-installing, it'd be really helpful.

Meantime the workaround does the job, not as neatly though.

merrittd at dhcmc dot com
28-Mar-2005 02:23

Example 43-2 shows how to create a DOS batch file to run a PHP script form the command line using:

@c:\php\cli\php.exe script.php %1 %2 %3 %4

Here is an updated version of the DOS batch file:

@c:\php\cli\php.exe %~n0.php %*

This will run a PHP file (i.e. script.php) with the same base file name (i.e. script) as the DOS batch file (i.e. script.bat) and pass all parameters (not just the first four as in example 43-2) from the DOS batch file to the PHP file. 

This way all you have to do is copy/rename the DOS batch file to match the name of your PHP script file without ever having to actually modify the contents of the DOS batch file to match the file name of the PHP script.

13-Mar-2005 02:52

Here is very simple, but usefull Command Line handler class. it may be usefull for your apps.

class AnyClass{
   public function start(){
       return "started";
   public function stop(){
       return "stoppded";
$cli = new CliHandler(new AnyClass());

CliHandler accepts any class als argument.
Try this.

/usr/local/php/PHP5 CliHandler.class.php
output: Try these command:
enter "start"
output: started

bertrand at toggg dot com
07-Mar-2005 09:40

If you want to pass directly PHP code to the interpreter and you don't have only CGI, not the CLI SAPI so you miss the -r option.
If you're lucky enough to be on a nix like system, then tou can still use the pipe solution as the 3. way to command CLI SAPI described above, using a pipe ('|').

Then works for CGI SAPI:

$ echo '<?php echo "coucou\n"; phpinfo(); /* or any code */ ?>' | php

NOTE: unlike commands passed to the -r option, here you NEED the PHP tags.

jeromenelson at gmail dot com
07-Mar-2005 02:21

This is the most simple way to get the named parameter.  Write the script test.php as ...

   echo "Yo! my name is ".$_REQUEST["name"]."\n";

and run this program as follows

# php -f test.php name=Jerry
Yo! my name is Jerry

I am using PHP 4.3.3 (CGI) in Fedora Core 1 and It is working perfectly

God Bless You!

obfuscated at emailaddress dot com
25-Feb-2005 09:15

This posting is not a php-only problem, but hopefully will save someone a few hours of headaches.  Running on MacOS (although this could happen on any *nix I suppose), I was unable to get the script to execute without specifically envoking php from the command line:

[macg4:valencia/jobs] tim% test.php
./test.php: Command not found.

However, it worked just fine when php was envoked on the command line:

[macg4:valencia/jobs] tim% php test.php
Well, here we are...  Now what?

Was file access mode set for executable?  Yup.

[macg4:valencia/jobs] tim% ls -l
total 16
-rwxr-xr-x  1 tim  staff  242 Feb 24 17:23 test.php

And you did, of course, remember to add the php command as the first line of your script, yeah?  Of course.

<?php print "Well, here we are...  Now what?\n"; ?>

So why dudn't it work?  Well, like I said... on a Mac.... but I also occasionally edit the files on my Windows portable (i.e. when I'm travelling and don't have my trusty Mac available)...  Using, say, WordPad on Windows... and BBEdit on the Mac...

Aaahhh... in BBEdit check how the file is being saved!  Mac?  Unix?  or Dos?  Bingo.  It had been saved as Dos format.  Change it to Unix:

[macg4:valencia/jobs] tim% ./test.php
Well, here we are...  Now what?
[macg4:valencia/jobs] tim%

NB: If you're editing your php files on multiple platforms (i.e. Windows and Linux), make sure you double check the files are saved in a Unix format...  those \r's and \n's 'll bite cha!

db at digitalmediacreation dot ch
22-Feb-2005 12:49

A very important point missing here (I lost hours on it and hope to avoid this to you) :

* When using PHP as CGI
* When you just become crazy because of "No input file specified" appearing on the web page, while it never appears directly in the shell

Then I have a solution for you :

1. Create a script for example called cgiwrapper.cgi
2. Put inside :
 #!/bin/sh -
 export SCRIPT_FILENAME=/var/www/realpage.php
 /usr/bin/php -f $SCRIPT_FILENAME
3. Name your page realpage.php

For example with thttpd the problem is that SCRIPT_FILENAME is not defined, while PHP absolutely requires it.
My solution corrects that problem !

11-Feb-2005 05:03

On windows try ctrl-m or ctrl-z to run code in interactive (-a) mode
(*nix ctrl-d)

ken.gregg at rwre dot com
09-Jan-2005 02:38

If you want to use named command line parameters in your script,
the following code will parse command line parameters in the form
of name=value and place them in the $_REQUEST super global array.


echo "argv[] = ";
print_r($argv);  // just to see what was passed in

if ($argc > 0)
  for ($i=1;$i < $argc;$i++)
   $_REQUEST = array_merge($_REQUEST, $tmp);

echo "\$_REQUEST = ";


rwre:~/tmp$ /usr/local/bin/php cli_test.php foo=1 bar=2 third=a+value

argv[] = Array
   [0] => t.php
   [1] => foo=1
   [2] => bar=2
   [3] => third=a+value
$_REQUEST = Array
   [foo] => 1
   [bar] => 2
   [third] => a value

Ben Jenkins
21-Dec-2004 10:23

This took me all day to figure out, so I hope posting it here saves someone some time:
Your PHP-CLI may have a different php.ini than your apache-php.  For example: On my Debian-based system, I discovered I have /etc/php4/apache/php.ini and /etc/php4/cli/php.ini
If you want MySQL support in the CLI, make sure the line
is not commented out.
The differences in php.ini files may also be why some scripts will work when called through a web browser, but will not work when called via the command line.

david at acz dot org
23-Sep-2004 01:46

If you want an interactive command line shell for PHP to test out code, give phpa a try:

linn at backendmedia dot com
06-Feb-2004 07:12

For those of you who want the old CGI behaviour that changes to the actual directory of the script use:

at the beginning of your scripts.

ben at slax0rnet dot com
02-Feb-2004 08:34

Just a note for people trying to use interactive mode from the commandline.

The purpose of interactive mode is to parse code snippits without actually leaving php, and it works like this:

[root@localhost php-4.3.4]# php -a
Interactive mode enabled

<?php echo "hi!"; ?>
<note, here we would press CTRL-D to parse everything we've entered so far>
<?php exit(); ?>
<ctrl-d here again>
[root@localhost php-4.3.4]#

I noticed this somehow got ommited from the docs, hope it helps someone!

phprsr at mindtwin dot com
05-Aug-2003 10:12

The basic issue was that PHP-as-CGI REALLY REALLY wants SCRIPT_FILENAME.
It ignores the command line. It ignores SCRIPT_NAME.  It wants

"No input file specified."

This very informative error message from PHP means that your web server, WHATEVER it is, is not setting SCRIPT_FILENAME.

The minimum set of env variables:

PATH: DOESN'T MATTER if you're spawning php pages with #!/../php in them
LD_LIBRARY_PATH= should be right
SERVER_SOFTWARE=mini_httpd/1.17beta1 26may2002
SERVER_NAME=who cares
SCRIPT_FILENAME=/homes/foobie/mini/foo.php    <--- CRITICAL
HTTP_USER_AGENT=Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)

If SCRIPT_FILENAME is not set, you'll get the dreaded "No input file specified" message.

mini_httpd does not do this by default. You need to patch it in to make_envp.

A secondary issue is configuration (PHP):

   ./configure --enable-discard-path --with-config-file-path=/homes/wherever/mini/php.ini
   (where php.ini is a slightly modified version of php.ini-recommended)

punk [_at_] studionew [_dot_] com
19-Jul-2003 05:18

You can use this function to ask user to enter smth

function read ($length='255')
   if (!isset ($GLOBALS['StdinPointer']))
     $GLOBALS['StdinPointer'] = fopen ("php://stdin","r");
   $line = fgets ($GLOBALS['StdinPointer'],$length);
   return trim ($line);

// then

echo "Enter your name: ";
$name = read ();
echo "\nHello $name! Where you came from? ";
$where = read ();
echo "\nI see. $where is very good place.";

Adam, php(at)
17-Jun-2003 05:12

Ok, I've had a heck of a time with PHP > 4.3.x and whether to use CLI vs CGI. The CGI version of 4.3.2 would return (in browser):
No input file specified.

And the CLI version would return:
500 Internal Server Error

It appears that in CGI mode, PHP looks at the environment variable PATH_TRANSLATED to determine the script to execute and ignores command line. That is why in the absensce of this environment variable, you get "No input file specified." However, in CLI mode the HTTP headers are not printed. I believe this is intended behavior for both situations but creates a problem when you have a CGI wrapper that sends environment variables but passes the actual script name on the command line.

By modifying my CGI wrapper to create this PATH_TRANSLATED environment variable, it solved my problem, and I was able to run the CGI build of 4.3.2

monte at ispi dot net
04-Jun-2003 04:47

I had a problem with the $argv values getting split up when they contained plus (+) signs. Be sure to use the CLI version, not CGI to get around it.


Popeye at P-t-B dot com
18-Apr-2003 09:15

In *nix systems, use the WHICH command to show the location of the php binary executable. This is the path to use as the first line in your php shell script file. (#!/path/to/php -q) And execute php from the command line with the -v switch to see what version you are running.


# which php
# php -v
PHP 4.3.1 (cli) (built: Mar 27 2003 14:41:51)
Copyright (c) 1997-2002 The PHP Group
Zend Engine v1.3.0, Copyright (c) 1998-2002 Zend Technologies

In the above example, you would use: #!/usr/local/bin/php

Also note that, if you do not have the current/default directory in your PATH (.), you will have to use ./scriptfilename to execute your script file from the command line (or you will receive a "command not found" error). Use the ENV command to show your PATH environment variable value.

volkany at celiknet dot com
20-Feb-2003 02:44

Here goes a very simple clrscr function for newbies...
function clrscr() { system("clear"); }

Alexander Plakidin
14-Feb-2003 06:34

How to change current directory in PHP script to script's directory when running it from command line using PHP 4.3.0?
(you'll probably need to add this to older scripts when running them under PHP 4.3.0 for backwards compatibility)

Here's what I am using:

Note: documentation says that "PHP_SELF" is not available in command-line PHP scripts. Though, it IS available. Probably this will be changed in future version, so don't rely on this line of code...

Use $_SERVER['PHP_SELF'] instead of just $PHP_SELF if you have register_globals=Off

c dot kelly[no--spam] at qfsaustrlia dot com dot au
06-Feb-2003 09:03

In Windows [NT4.0 sp6a] the example
php -r ' echo getcwd();' does not work ; It appears you have to use the following php -r "echo getcwd();" --not the " around the command  to get the output to screen , just took me half an hour to figure out what was going on.

wanna at stay dot anonynous dot com
22-Jan-2003 10:42

TIP: If you want different versions of the configuration file  depending on what SAPI is used,just name them php.ini (apache module), php-cli.ini (CLI) and php-cgi.ini (CGI) and dump them all in the regular configuration directory. I.e no need to compile several versions of php anymore!

phpnotes at ssilk dot de
22-Oct-2002 04:36

To hand over the GET-variables in interactive mode like in HTTP-Mode (e.g. your URI is myprog.html?hugo=bla&bla=hugo), you have to call

php myprog.html '&hugo=bla&bla=hugo'

(two & instead of ? and &!)

There just a little difference in the $ARGC, $ARGV values, but I think this is in those cases not relevant.

justin at visunet dot ie
21-Oct-2002 10:21

If you are trying to set up an interactive command line script and you want to get started straight away (works on 4+ I hope). Here is some code to start you off:


   // Stop the script giving time out errors..

   // This opens standard in ready for interactive input..

   // Main event loop to capture top level command..
       // Print out main menu..
       echo "Select an option..\n\n";
       echo "    1) Do this\n";
       echo "    2) Do this\n";
       echo "    3) Do this\n";
       echo "    x) Exit\n";

       // Decide what menu option to select based on input..
           case 1:
           case 2:

           case 3:

           case "x":


   // Close standard in..


phpNOSPAM at dogpoop dot cjb dot net
11-Oct-2002 09:28

Here are some instructions on how to make PHP files executable from the command prompt in Win2k.  I have not tested this in any other version of Windows, but I'm assuming it will work in XP, but not 9x/Me.

There is an environment variable (control panel->system->advanced->environment variables) named PATHEXT.  This is a list of file extensions Windows will recognize as executable at the command prompt.  Add .PHP (or .PL, or .CLASS, or whatever) to this list.  Windows will use the default action associated with that file type when you execute it from the command prompt.

To set up the default action:
Open Explorer.
Go to Tools->folder options->file types
Find the extension you're looking for.  If it's not there, click New to add it.
Click on the file type, then on Advanced, then New.
For the action, type "Run" or "Execute" or whatever makes sense.
For the application, type
  {path to application} "%1" %*
The %* will send any command line options that you type to the program.
The application field for PHP might look like
  c:\php\php.exe -f "%1" -- %*
(Note, you'll probably want to use the command line interface version php-cli.exe)
or for Java
  c:\java\java.exe "%1" %*
Click OK.
Click on the action that was just added, then click Set default.

If this helps you or if you have any changes/more information I would appreciate a note.  Just remove NOSPAM from the email address.

jeff at noSpam[] dot genhex dot net
06-Sep-2002 06:13

You can also call the script from the command line after chmod'ing the file (ie: chmod 755 file.php).

On your first line of the file, enter "#!/usr/bin/php" (or to wherever your php executable is located).  If you want to suppress the PHP headers, use the line of "#!/usr/bin/php -q" for your path.

15-Aug-2002 12:15

Under Solaris (at least 2.6) I have some problems with reading stdin. Original pbms report may be found here:

At a first glance the only solution for it is 'fgetcsv'

#!/usr/local/bin/php -q

if (!$fd)

while (!feof ($fd))
  $s = fgetcsv($fd,128,"\n");
  if ($s==false)

  echo $s[0]."\n";

But... keep reading....

>>> I wrote
Sometimes I hate PHP... ;)

Right today I was trapped by some strange bug in my code with reading stdin using fgetcsv.
After a not small investigation I found that strings like "foo\nboo\ndoo"goo\n (take note of double quatation sign in it)
interpreted by fgetcsv like:
since double quotation mark has a special meaning and get stripped off of the input stream.
Indeed, according to PHP manual:
array fgetcsv ( int fp, int length [, string delimiter [, string enclosure]])

another delimiter with the optional third parameter. _The_enclosure_character_is_double_quote_,_unless_
_enclosure_is_added_from_PHP 4.3.0.      !!!!!!

Means no chance for us prior to 4.3.0 :(
But file() works just fine !!!! Of course by the price of memory, so be careful with large files.

set_magic_quotes_runtime(0); // important, do not forget it !!!
for ($i=0,$n=sizeof($s);$i<$n;$i++)

1. If you have no double quotation mark in your data use fgetcsv
2. From 4.3.0 use  fgetcsv($fd,"\n",""); // I hope it will help
3. If you data is not huge use file("php://stdin");

Hope now it's cleared for 100% (to myself ;)

Good luck!

PS. Don't forget that it's only Solaris specific problem. Under Linux just use usual fgets()...

jonNO at SPAMjellybob dot co dot uk
03-Aug-2002 10:17

If you want to get the output of a command use the function shell_exec($command) - it returns a string with the output of the command.

ben-php dot net at wefros dot com
13-Jun-2002 04:40

PHP 4.3 and above automatically have STDOUT, STDIN, and STDERR openned ... but < 4.3.0 do not.  This is how you make code that will work in versions previous to PHP 4.3 and future versions without any changes:

   if (version_compare(phpversion(),'4.3.0','<')) {
       register_shutdown_function( create_function( '' , 'fclose(STDIN); fclose(STDOUT); fclose(STDERR); return true;' ) );

/* get some STDIN up to 256 bytes */
   $str = fgets(STDIN,256);

philip at cornado dot com
25-Feb-2002 03:02

See also:

pyxl at jerrell dot com
18-Feb-2002 12:52

Assuming --prefix=/usr/local/php, it's better to create a symlink from /usr/bin/php or /usr/local/bin/php to target /usr/local/php/bin/php so that it's both in your path and automatically correct every time you rebuild.  If you forgot to do that copy of the binary after a rebuild, you can do all kinds of wild goose chasing when things break.

Last updated: February 19, 2014

mechanical or whatever engineering. If someone said "well I like using bamboo to build bridges, I'm going to build a 6 lane highway with it" we'd laugh. This guy is talking about the same sorts of things and promoting a language that has none of the advantages of bamboo for bridge building.

At least with people and languages like this, I'll never be unemployed, as there will always be buggered systems to fix or replace.

Newton stood on the shoulders of giants, we fail even to build on the work of pygmies.
Returns a boolean indicating whether the SV contains an integer.

int SvIOK (SV* SV)

Unsets the IV status of an SV.

SvIOK_off (SV* sv)

Tells an SV that it is an integer.

SvIOK_on (SV* sv)

Tells an SV that it is an integer and disables all other OK bits.

SvIOK_on (SV* sv)

Tells an SV that it is an integer and disables all other OK bits.

SvIOK_on (SV* sv)

Returns a boolean indicating whether the SV contains an integer. Checks the private  setting. Use SvIOK .

int SvIOKp (SV* SV)

Returns a boolean indicating whether the SV is blessed into the specified class. This does not know how to check for subtype, so it doesn't work in an inheritance relationship.

Returns the integer which is in the SV.

int SvIV (SV* sv)

Returns a boolean indicating whether the SV is an RV pointing to a blessed object. If the SV is not an RV, or if the object is not blessed, then this will return false.

Returns the integer which is stored in the SV.

int SvIVX (SV* sv);

Returns the size of the string buffer in the SV. See SvCUR .

int SvLEN (SV* sv)

Returns the length of the string in the SV. Use SvCUR .

Returns the length of the string in the SV. Use SvCUR .

Adds magic to an SV.

Creates a new SV which is a copy of the original SV. The new SV is marked as mortal.

SV* sv_mortalcopy _((SV* oldsv));

Returns a boolean indicating whether the value is an SV.

int SvOK (SV* sv)

Creates a new SV which is mortal. The refcount of the SV is set to 1.

SV* sv_newmortal _((void));

This is the false SV. See sv_yes . Always refer to this as &sv_no.

Returns a boolean indicating whether the SV contains a number, integer or double.

int SvNIOK (SV* SV)

Unsets the NV/IV status of an SV.

SvNIOK_off (SV* sv)

Returns a boolean indicating whether the SV contains a number, integer or double. Checks the private  setting. Use SvNIOK .

int SvNIOKp (SV* SV)

Returns a boolean indicating whether the SV contains a double.

int SvNOK (SV* SV)

Unsets the NV status of an SV.

SvNOK_off (SV* sv)

Tells an SV that it is a double.

SvNOK_on (SV* sv)

Tells an SV that it is a double and disables all other OK bits.

SvNOK_on (SV* sv)

Tells an SV that it is a double and disables all other OK bits.

SvNOK_on (SV* sv)

Returns a boolean indicating whether the SV contains a double. Checks the private  setting. Use SvNOK .

int SvNOKp (SV* SV)

Returns the double which is stored in the SV.

double SvNV (SV* sv);

Returns the double which is stored in the SV.

double SvNVX (SV* sv);

Returns a boolean indicating whether the SV contains a character string.

int SvPOK (SV* SV)

Unsets the PV status of an SV.

SvPOK_off (SV* sv)

Tells an SV that it is a string.

SvPOK_on (SV* sv)

Tells an SV that it is a string and disables all other OK bits.

SvPOK_on (SV* sv)

Tells an SV that it is a string and disables all other OK bits.

SvPOK_on (SV* sv)

Returns a boolean indicating whether the SV contains a character string. Checks the private  setting. Use SvPOK .

int SvPOKp (SV* SV)

Returns a pointer to the string in the SV, or a stringified form of the SV if the SV does not contain a string. If len is na then Perl will handle the length on its own.

char * SvPV (SV* sv, int len )

Returns a pointer to the string in the SV. The SV must contain a string.

char * SvPVX (SV* sv)

Returns the value of the object's refcount.

int SvREFCNT (SV* sv);

Decrements the refcount of the given SV.

void SvREFCNT_dec (SV* sv)

Increments the refcount of the given SV.

void SvREFCNT_inc (SV* sv)

Tests if the SV is an RV.

int SvROK (SV* sv)

Unsets the RV status of an SV.

SvROK_off (SV* sv)

Tells an SV that it is an RV.

SvROK_on (SV* sv)

Dereferences an RV to return the SV.

SV* SvRV (SV* sv);

Copies an integer into the given SV.

Copies a double into the given SV.

Copies a string into an SV. The string must be null-terminated.

Copies a string into an SV. The len parameter indicates the number of bytes to be copied.

Copies an integer into a new SV, optionally blessing the SV. The rv argument will be upgraded to an RV. That RV will be modified to point to the new SV. The classname argument indicates the package for the blessing. Set classname to Nullch to avoid the blessing. The new SV will be returned and will have a refcount of 1.

SV* sv_setref_iv _((SV *rv, char *classname, IV iv));

Copies a double into a new SV, optionally blessing the SV. The rv argument will be upgraded to an RV. That RV will be modified to point to the new SV. The classname argument indicates the package for the blessing. Set classname to Nullch to avoid the blessing. The new SV will be returned and will have a refcount of 1.

SV* sv_setref_nv _((SV *rv, char *classname, double nv));

Copies a pointer into a new SV, optionally blessing the SV. The rv argument will be upgraded to an RV. That RV will be modified to point to the new SV. If the pv argument is NULL then sv_undef will be placed into the SV. The classname argument indicates the package for the blessing. Set classname to Nullch to avoid the blessing. The new SV will be returned and will have a refcount of 1.

SV* sv_setref_pv _((SV *rv, char *classname, void* pv));

Do not use with integral Perl types such as HV, AV, SV, CV, because those objects will become corrupted by the pointer copy process.

Note that sv_setref_pvn copies the string while this copies the pointer.

Copies a string into a new SV, optionally blessing the SV. The length of the string must be specified with n. The rv argument will be upgraded to an RV. That RV will be modified to point to the new SV. The classname argument indicates the package for the blessing. Set classname to Nullch to avoid the blessing. The new SV will be returned and will have a refcount of 1.

SV* sv_setref_pvn _((SV *rv, char *classname, char* pv, I32 n));

Note that sv_setref_pv copies the pointer while this copies the string.

Copies the contents of the source SV ssv into the destination SV dsv. The source SV may be destroyed if it is mortal.

Returns the stash of the SV.

HV * SvSTASH (SV* sv)

Integer type flag for scalars. See svtype .

Pointer type flag for scalars. See svtype .

Type flag for arrays. See svtype .

Type flag for code refs. See svtype .

Type flag for hashes. See svtype .

Type flag for blessed scalars. See svtype .

Double type flag for scalars. See svtype .

Returns a boolean indicating whether Perl would evaluate the SV as true or false, defined or undefined.

int SvTRUE (SV* sv)

Returns the type of the SV. See svtype .

An enum of flags for Perl types. These are found in the file sv.h  in the svtype enum. Test these flags with the SvTYPE macro.

Used to upgrade an SV to a more complex form. Uses sv_upgrade to perform the upgrade if necessary. See svtype .

bool SvUPGRADE _((SV* sv, svtype mt));

Upgrade an SV to a more complex form. Use SvUPGRADE . See svtype .

This is the undef SV. Always refer to this as &sv_undef.

Unsets the RV status of the SV, and decrements the refcount of whatever was being referenced by the RV. This can almost be thought of as a reversal of newSVrv . See SvROK_off .

void sv_unref _((SV* sv));

Tells an SV to use ptr to find its string value. Normally the string is stored inside the SV but sv_usepvn allows the SV to use an outside string. The ptr should point to memory that was allocated by malloc. The string length, len, must be supplied. This function will realloc the memory pointed to by ptr, so that pointer should not be freed or used by the programmer after giving it to sv_usepvn.

This is the true SV. See sv_no . Always refer to this as &sv_yes.

Variable which is setup by xsubpp to designate the object in a C++ XSUB. This is always the proper type for the C++ object. See CLASS and ``Using XS With C++''.

Converts the specified character to lowercase.

int toLOWER (char c)

Converts the specified character to uppercase.

int toUPPER (char c)

This is the XSUB-writer's interface to Perl's warn function. Use this function the same way you use the C printf function. See croak() .

Push an integer onto the stack, extending the stack if necessary. See PUSHi .

XPUSHi(int d)

Push a double onto the stack, extending the stack if necessary. See PUSHn .

XPUSHn(double d)

Push a string onto the stack, extending the stack if necessary. The len indicates the length of the string. See PUSHp .

XPUSHp(char *c, int len)

Push an SV onto the stack, extending the stack if necessary. See PUSHs .


Macro to declare an XSUB and its C parameter list. This is handled by xsubpp.

Return from XSUB, indicating number of items on the stack. This is usually handled by xsubpp.

XSRETURN(int x);

Return an empty list from an XSUB immediately.


Return an integer from an XSUB immediately. Uses XST_mIV .


Return &sv_no from an XSUB immediately. Uses XST_mNO .


Return an double from an XSUB immediately. Uses XST_mNV .


Return a copy of a string from an XSUB immediately. Uses XST_mPV .

XSRETURN_PV(char *v);

Return &sv_undef from an XSUB immediately. Uses XST_mUNDEF .


Return &sv_yes from an XSUB immediately. Uses XST_mYES .


Place an integer into the specified position i on the stack. The value is stored in a new mortal SV.

XST_mIV( int i, IV v );

Place a double into the specified position i on the stack. The value is stored in a new mortal SV.

XST_mNV( int i, NV v );

Place &sv_no into the specified position i on the stack.

XST_mNO( int i );

Place a copy of a string into the specified position i on the stack. The value is stored in a new mortal SV.

XST_mPV( int i, char *v );

Place &sv_undef into the specified position i on the stack.

XST_mUNDEF( int i );

Place &sv_yes into the specified position i on the stack.

XST_mYES( int i );

The version identifier for an XS module. This is usually handled automatically by ExtUtils::MakeMaker. See XS_VERSION_BOOTCHECK .

Macro to verify that a PM module's $VERSION  variable matches the XS module's XS_VERSION variable. This is usually handled automatically by xsubpp. See ``The VERSIONCHECK: Keyword''.

The XSUB-writer's interface to the C memzero function. The d is the destination, n is the number of items, and t is the type.

(void) Zero( d, n, t );


Jeff Okamoto <>

With lots of help and suggestions from Dean Roehrich, Malcolm Beattie, Andreas Koenig, Paul Hudson, Ilya Zakharevich, Paul Marquess, Neil Bowers, Matthew Green, Tim Bunce, and Spider Boardman.

API Listing by Dean Roehrich <>.


Version 22: 1996/9/23 Where a number would appear in the flags, an asterisk (``*'') may be used instead, in which case Perl uses the next item in the parameter list as the given number (that is, as the field width or precision). If a field width obtained through ``*'' is negative, it has the same effect as the ``-'' flag: left-justification.

If use locale is in effect, the character used for the decimal point in formatted real numbers is affected by the LC_NUMERIC locale. See perllocale.

sqrt EXPR

Return the square root of EXPR. If EXPR is omitted, returns square root of $_. Only works on non-negative operands, unless you've loaded the standard Math::Complex module.

    use Math::Complex;
    print sqrt(-2);    # prints 1.4142135623731i
srand EXPR

Sets the random number seed for the rand() operator. If EXPR is omitted, uses a semi-random value supplied by the kernel (if it supports the /dev/urandom device) or based on the current time and process ID, among other things. In versions of Perl prior to 5.004 the default seed was just the current time(). This isn't a particularly good seed, so many old programs supply their own seed value (often time ^ $$ or time ^ ($$ + ($$ &lt;&lt; 15))), but that isn't necessary any more.

In fact, it's usually not necessary to call srand() at all, because if it is not called explicitly, it is called implicitly at the first use of the rand() operator. However, this was not the case in version of Perl before 5.004, so if your script will run under older Perl versions, it should call srand().

Note that you need something much more random than the default seed for cryptographic purposes. Checksumming the compressed output of one or more rapidly changing operating system status programs is the usual method. For example:

    srand (time ^ $$ ^ unpack "%L*", `ps axww | gzip`);

If you're particularly concerned with this, see the Math::TrulyRandom module in CPAN.

Do not call srand() multiple times in your program unless you know exactly what you're doing and why you're doing it. The point of the function is to ``seed'' the rand() function so that rand() can produce a different sequence each time you run your program. Just do it once at the top of your program, or you won't get random numbers out of rand()!

Frequently called programs (like CGI scripts) that simply use

    time ^ $$

for a seed can fall prey to the mathematical property that

    a^b == (a+1)^(b+1)

one-third of the time. So don't do that.

stat EXPR

Returns a 13-element list giving the status info for a file, either the file opened via FILEHANDLE, or named by EXPR. If EXPR is omitted, it stats $_. Returns a null list if the stat fails. Typically used as follows:

           = stat($filename);

Not all fields are supported on all filesystem types. Here are the meaning of the fields:

  0 dev      device number of filesystem
  1 ino      inode number
  2 mode     file mode  (type and permissions)
  3 nlink    number of (hard) links to the file
  4 uid      numeric user ID of file's owner
  5 gid      numeric group ID of file's owner
  6 rdev     the device identifier (special files only)
  7 size     total size of file, in bytes
  8 atime    last access time since the epoch
  9 mtime    last modify time since the epoch
 10 ctime    inode change time (NOT creation time!) since the epoch
 11 blksize  preferred block size for file system I/O
 12 blocks   actual number of blocks allocated

(The epoch was at 00:00 January 1, 1970 GMT.)

If stat is passed the special filehandle consisting of an underline, no stat is done, but the current contents of the stat structure from the last stat or filetest are returned. Example:

    if (-x $file && (($d) = stat(_)) && $d < 0) {
        print "$file is executable NFS file\n";

(This works on machines only for which the device number is negative under NFS.)

Because the mode contains both the file type and its permissions, you should mask off the file type portion and (s)printf using a "%o" if you want to see the real permissions.

    $mode = (stat($filename))[2];
    printf "Permissions are %04o\n", $mode & 07777;

In scalar context, stat() returns a boolean value indicating success or failure, and, if successful, sets the information associated with the special filehandle _.

The File::stat module provides a convenient, by-name access mechanism:

    use File::stat;
    $sb = stat($filename);
    printf "File is %s, size is %s, perm %04o, mtime %s\n", 
        $filename, $sb->size, $sb->mode & 07777,
        scalar localtime $sb->mtime;
study SCALAR

Takes extra time to study SCALAR ($_ if unspecified) in anticipation of doing many pattern matches on the string before it is next modified. This may or may not save time, depending on the nature and number of patterns you are searching on, and on the distribution of character frequencies in the string to be searched -- you probably want to compare run times with and without it to see which runs faster. Those loops which scan for many short constant strings (including the constant parts of more complex patterns) will benefit most. You may have only one study() active at a time -- if you study a different scalar the first is ``unstudied''. (The way study() works is this: a linked list of every character in the string to be searched is made, so we know, for example, where all the 'k' characters are. From each search string, the rarest character is selected, based on some static frequency tables constructed from some C programs and English text. Only those places that contain this ``rarest'' character are examined.)

For example, here is a loop that inserts index producing entries before any line containing a certain pattern:

    while (<>) {
        print ".IX foo\n"       if /\bfoo\b/;
        print ".IX bar\n"       if /\bbar\b/;
        print ".IX blurfl\n"    if /\bblurfl\b/;
        # ...

In searching for /\bfoo\b/, only those locations in $_ that contain "f" will be looked at, because "f" is rarer than "o". In general, this is a big win except in pathological cases. The only question is whether it saves you more time than it took to build the linked list in the first place.

Note that if you have to look for strings that you don't know till runtime, you can build an entire loop as a string and eval() that to avoid recompiling all your patterns all the time. Together with undefining $/ to input entire files as one record, this can be very fast, often faster than specialized programs like fgrep(1). The following scans a list of files (@files) for a list of words (@words), and prints out the names of those files that contain a match:

    $search = 'while (<>) { study;';
    foreach $word (@words) {
        $search .= "++\$seen{\$ARGV} if /\\b$word\\b/;\n";
    $search .= "}";
    @ARGV = @files;
    undef $/;
    eval $search;               # this screams
    $/ = "\n";          # put back to normal input delimiter
    foreach $file (sort keys(%seen)) {
        print $file, "\n";
sub NAME

This is subroutine definition, not a real function per se. With just a NAME (and possibly prototypes), it's just a forward declaration. Without a NAME, it's an anonymous function declaration, and does actually return a value: the CODE ref of the closure you just created. See perlsub and perlref for details.


Extracts a substring out of EXPR and returns it. First character is at offset 0, or whatever you've set $[ to (but don't do that). If OFFSET is negative (or more precisely, less than $[), starts that far from the end of the string. If LEN is omitted, returns everything to the end of the string. If LEN is negative, leaves that many characters off the end of the string.

If you specify a substring that is partly outside the string, the part within the string is returned. If the substring is totally outside the string a warning is produced.

You can use the substr() function as an lvalue, in which case EXPR must itself be an lvalue. If you assign something shorter than LEN, the string will shrink, and if you assign something longer than LEN, the string will grow to accommodate it. To keep the string the same length you may need to pad or chop your value using sprintf().

An alternative to using substr() as an lvalue is to specify the replacement string as the 4th argument. This allows you to replace parts of the EXPR and return what was there before in one operation, just as you can with splice().


Creates a new filename symbolically linked to the old filename. Returns 1 for success, 0 otherwise. On systems that don't support symbolic links, produces a fatal error at run time. To check for that, use eval:

    $symlink_exists = eval { symlink("",""); 1 };
syscall LIST

Calls the system call specified as the first element of the list, passing the remaining elements as arguments to the system call. If unimplemented, produces a fatal error. The arguments are interpreted as follows: if a given argument is numeric, the argument is passed as an int. If not, the pointer to the string value is passed. You are responsible to make sure a string is pre-extended long enough to receive any result that might be written into a string. You can't use a string literal (or other read-only string) as an argument to syscall() because Perl has to assume that any string pointer might be written through. If your integer arguments are not literals and have never been interpreted in a numeric context, you may need to add 0 to them to force them to look like numbers. This emulates the syswrite() function (or vice versa):

    require '';               # may need to run h2ph
    $s = "hi there\n";
    syscall(&SYS_write, fileno(STDOUT), $s, length $s);

Note that Perl supports passing of up to only 14 arguments to your system call, which in practice should usually suffice.

Syscall returns whatever value returned by the system call it calls. If the system call fails, syscall() returns -1 and sets $! (errno). Note that some system calls can legitimately return -1. The proper way to handle such calls is to assign $!=0; before the call and check the value of $! if syscall returns -1.

There's a problem with syscall(&SYS_pipe): it returns the file number of the read end of the pipe it creates. There is no way to retrieve the file number of the other end. You can avoid this problem by using pipe() instead.


Opens the file whose filename is given by FILENAME, and associates it with FILEHANDLE. If FILEHANDLE is an expression, its value is used as the name of the real filehandle wanted. This function calls the underlying operating system's open() function with the parameters FILENAME, MODE, PERMS.

The possible values and flag bits of the MODE parameter are system-dependent; they are available via the standard module Fcntl. For historical reasons, some values work on almost every system supported by perl: zero means read-only, one means write-only, and two means read/write. We know that these values do not work under OS/390 & VM/ESA Unix and on the Macintosh; you probably don't want to use them in new code.

If the file named by FILENAME does not exist and the open() call creates it (typically because MODE includes the O_CREAT flag), then the value of PERMS specifies the permissions of the newly created file. If you omit the PERMS argument to sysopen(), Perl uses the octal value 0666. These permission values need to be in octal, and are modified by your process's current umask.

You should seldom if ever use 0644 as argument to sysopen(), because that takes away the user's option to have a more permissive umask. Better to omit it. See the perlfunc(1) entry on umask for more on this.

See perlopentut for a kinder, gentler explanation of opening files.


Attempts to read LENGTH bytes of data into variable SCALAR from the specified FILEHANDLE, using the system call read(2). It bypasses stdio, so mixing this with other kinds of reads, print(), write(), seek(), tell(), or eof() can cause confusion because stdio usually buffers data. Returns the number of bytes actually read, 0 at end of file, or undef if there was an error. SCALAR will be grown or shrunk so that the last byte actually read is the last byte of the scalar after the read.

An OFFSET may be specified to place the read data at some place in the string other than the beginning. A negative OFFSET specifies placement at that many bytes counting backwards from the end of the string. A positive OFFSET greater than the length of SCALAR results in the string being padded to the required size with "\0" bytes before the result of the read is appended.

There is no syseof() function, which is ok, since eof() doesn't work very well on device files (like ttys) anyway. Use sysread() and check for a return value for 0 to decide whether you're done.


Sets FILEHANDLE's system position using the system call lseek(2). It bypasses stdio, so mixing this with reads (other than sysread()), print(), write(), seek(), tell(), or eof() may cause confusion. FILEHANDLE may be an expression whose value gives the name of the filehandle. The values for WHENCE are 0 to set the new position to POSITION, 1 to set the it to the current position plus POSITION, and 2 to set it to EOF plus POSITION (typically negative). For WHENCE, you may use the constants SEEK_SET, SEEK_CUR, and SEEK_END from either the IO::Seekable or the POSIX module.

Returns the new position, or the undefined value on failure. A position of zero is returned as the string ``0 but true''; thus sysseek() returns TRUE on success and FALSE on failure, yet you can still easily determine the new position.

system LIST

Does exactly the same thing as ``exec LIST'', except that a fork is done first, and the parent process waits for the child process to complete. Note that argument processing varies depending on the number of arguments. If there is more than one argument in LIST, or if LIST is an array with more than one value, starts the program given by the first element of the list with arguments given by the rest of the list. If there is only one scalar argument, the argument is checked for shell metacharacters, and if there are any, the entire argument is passed to the system's command shell for parsing (this is /bin/sh -c on Unix platforms, but varies on other platforms). If there are no shell metacharacters in the argument, it is split into words and passed directly to execvp(), which is more efficient.

The return value is the exit status of the program as returned by the wait() call. To get the actual exit value divide by 256. See also exec. This is NOT what you want to use to capture the output from a command, for that you should use merely backticks or qx//, as described in perlop.

Like exec(), system() allows you to lie to a program about its name if you use the ``system PROGRAM LIST'' syntax. Again, see exec.

Because system() and backticks block SIGINT and SIGQUIT, killing the program they're running doesn't actually interrupt your program.

    @args = ("command", "arg1", "arg2");
    system(@args) == 0
         or die "system @args failed: $?"

You can check all the failure possibilities by inspecting $? like this:

    $exit_value  = $? >> 8;
    $signal_num  = $? & 127;
    $dumped_core = $? & 128;

When the arguments get executed via the system shell, results and return codes will be subject to its quirks and capabilities. See perlop and exec for details.


Attempts to write LENGTH bytes of data from variable SCALAR to the specified FILEHANDLE, using the system call write(2). If LENGTH is not specified, writes whole SCALAR. It bypasses stdio, so mixing this with reads (other than sysread()), print(), write(), seek(), tell(), or eof() may cause confusion because stdio usually buffers data. Returns the number of bytes actually written, or undef if there was an error. If the LENGTH is greater than the available data in the SCALAR after the OFFSET, only as much data as is available will be written.

An OFFSET may be specified to write the data from some part of the string other than the beginning. A negative OFFSET specifies writing that many bytes counting backwards from the end of the string. In the case the SCALAR is empty you can use OFFSET but only zero offset.


Returns the current position for FILEHANDLE. FILEHANDLE may be an expression whose value gives the name of the actual filehandle. If FILEHANDLE is omitted, assumes the file last read.

There is no systell() function. Use sysseek(FH, 0, 1) for that.


Returns the current position of the readdir() routines on DIRHANDLE. Value may be given to seekdir() to access a particular location in a directory. Has the same caveats about possible directory compaction as the corresponding system library routine.


This function binds a variable to a package class that will provide the implementation for the variable. VARIABLE is the name of the variable to be enchanted. CLASSNAME is the name of a class implementing objects of correct type. Any additional arguments are passed to the ``new()'' method of the class (meaning TIESCALAR, TIEHANDLE, TIEARRAY, or TIEHASH). Typically these are arguments such as might be passed to the dbm_open() function of C. The object returned by the ``new()'' method is also returned by the tie() function, which would be useful if you want to access other methods in CLASSNAME.

Note that functions such as keys() and values() may return huge lists when used on large objects, like DBM files. You may prefer to use the each() function to iterate over such. Example:

    # print out history file offsets
    use NDBM_File;
    tie(%HIST, 'NDBM_File', '/usr/lib/news/history', 1, 0);
    while (($key,$val) = each %HIST) {
        print $key, ' = ', unpack('L',$val), "\n";

A class implementing a hash should have the following methods:

    TIEHASH classname, LIST
    FETCH this, key
    STORE this, key, value
    DELETE this, key
    CLEAR this
    EXISTS this, key
    FIRSTKEY this
    NEXTKEY this, lastkey
    DESTROY this

A class implementing an ordinary array should have the following methods:

    TIEARRAY classname, LIST
    FETCH this, key
    STORE this, key, value
    FETCHSIZE this
    STORESIZE this, count
    CLEAR this
    PUSH this, LIST
    POP this
    SHIFT this
    UNSHIFT this, LIST
    SPLICE this, offset, length, LIST
    EXTEND this, count
    DESTROY this

A class implementing a file handle should have the following methods:

    TIEHANDLE classname, LIST
    READ this, scalar, length, offset
    READLINE this
    GETC this
    WRITE this, scalar, length, offset
    PRINT this, LIST
    PRINTF this, format, LIST
    CLOSE this
    DESTROY this

A class implementing a scalar should have the following methods:

    TIESCALAR classname, LIST
    FETCH this,
    STORE this, value
    DESTROY this

Not all methods indicated above need be implemented. See perltie, Tie::Hash, Tie::Array, Tie::Scalar, and Tie::Handle.

Unlike dbmopen(), the tie() function will not use or require a module for you--you need to do that explicitly yourself. See DB_File or the Config module for interesting tie() implementations.

For further details see perltie, tied VARIABLE.


Returns a reference to the object underlying VARIABLE (the same value that was originally returned by the tie() call that bound the variable to a package.) Returns the undefined value if VARIABLE isn't tied to a package.


Returns the number of non-leap seconds since whatever time the system considers to be the epoch (that's 00:00:00, January 1, 1904 for MacOS, and 00:00:00 UTC, January 1, 1970 for most other systems). Suitable for feeding to gmtime() and localtime().


Returns a four-element list giving the user and system times, in seconds, for this process and the children of this process.

    ($user,$system,$cuser,$csystem) = times;

The transliteration operator. Same as y///. See perlop.

truncate EXPR,LENGTH

Truncates the file opened on FILEHANDLE, or named by EXPR, to the specified length. Produces a fatal error if truncate isn't implemented on your system. Returns TRUE if successful, the undefined value otherwise.


Returns an uppercased version of EXPR. This is the internal function implementing the \U escape in double-quoted strings. Respects current LC_CTYPE locale if use locale in force. See perllocale. (It does not attempt to do titlecase mapping on initial letters. See ucfirst() for that.)

If EXPR is omitted, uses $_.

ucfirst EXPR

Returns the value of EXPR with the first character in uppercase. This is the internal function implementing the \u escape in double-quoted strings. Respects current LC_CTYPE locale if use locale in force. See perllocale.

If EXPR is omitted, uses $_.

umask EXPR

Sets the umask for the process to EXPR and returns the previous value. If EXPR is omitted, merely returns the current umask.

The Unix permission rwxr-x--- is represented as three sets of three bits, or three octal digits: 0750 (the leading 0 indicates octal and isn't one of the digits). The umask value is such a number representing disabled permissions bits. The permission (or ``mode'') values you pass mkdir or sysopen are modified by your umask, so even if you tell sysopen to create a file with permissions 0777, if your umask is 0022 then the file will actually be created with permissions 0755. If your umask were 0027 (group can't write; others can't read, write, or execute), then passing sysopen() 0666 would create a file with mode 0640 (0666 &~ 027 is 0640).

Here's some advice: supply a creation mode of 0666 for regular files (in sysopen()) and one of 0777 for directories (in mkdir()) and executable files. This gives users the freedom of choice: if they want protected files, they might choose process umasks of 022, 027, or even the particularly antisocial mask of 077. Programs should rarely if ever make policy decisions better left to the user. The exception to this is when writing files that should be kept private: mail files, web browser cookies, .rhosts files, and so on.

If umask(2) is not implemented on your system and you are trying to restrict access for yourself (i.e., (EXPR & 0700) > 0), produces a fatal error at run time. If umask(2) is not implemented and you are not trying to restrict access for yourself, returns undef.

Remember that a umask is a number, usually given in octal; it is not a string of octal digits. See also oct, if all you have is a string.

undef EXPR

Undefines the value of EXPR, which must be an lvalue. Use only on a scalar value, an array (using ``@''), a hash (using ``%''), a subroutine (using ``&''), or a typeglob (using ``<*>''). (Saying undef $hash{$key} will probably not do what you expect on most predefined variables or DBM list values, so don't do that; see delete.) Always returns the undefined value. You can omit the EXPR, in which case nothing is undefined, but you still get an undefined value that you could, for instance, return from a subroutine, assign to a variable or pass as a parameter. Examples:

    undef $foo;
    undef $bar{'blurfl'};      # Compare to: delete $bar{'blurfl'};
    undef @ary;
    undef %hash;
    undef &mysub;
    undef *xyz;       # destroys $xyz, @xyz, %xyz, &xyz, etc.
    return (wantarray ? (undef, $errmsg) : undef) if $they_blew_it;
    select undef, undef, undef, 0.25;
    ($a, $b, undef, $c) = &foo;       # Ignore third value returned

Note that this is a unary operator, not a list operator.

unlink LIST

Deletes a list of files. Returns the number of files successfully deleted.

    $cnt = unlink 'a', 'b', 'c';
    unlink @goners;
    unlink <*.bak>;

Note: unlink() will not delete directories unless you are superuser and the -U  flag is supplied to Perl. Even if these conditions are met, be warned that unlinking a directory can inflict damage on your filesystem. Use rmdir() instead.

If LIST is omitted, uses $_.


Unpack() does the reverse of pack(): it takes a string representing a structure and expands it out into a list value, returning the array value. (In scalar context, it returns merely the first value produced.) The TEMPLATE has the same format as in the pack() function. Here's a subroutine that does substring:

    sub substr {
        my($what,$where,$howmuch) = @_;
        unpack("x$where a$howmuch", $what);

and then there's

    sub ordinal { unpack("c",$_[0]); } # same as ord()

In addition, you may prefix a field with a %<number> to indicate that you want a <number>-bit checksum of the items instead of the items themselves. Default is a 16-bit checksum. For example, the following computes the same number as the System V sum program:

    while (<>) {
        $checksum += unpack("%32C*", $_);
    $checksum %= 65535;

The following efficiently counts the number of set bits in a bit vector:

    $setbits = unpack("%32b*", $selectmask);

See pack for more examples.


Breaks the binding between a variable and a package. (See tie().)

unshift ARRAY,LIST

Does the opposite of a shift(). Or the opposite of a push(), depending on how you look at it. Prepends list to the front of the array, and returns the new number of elements in the array.

    unshift(ARGV, '-e') unless $ARGV[0] =~ /^-/;

Note the LIST is prepended whole, not one element at a time, so the prepended elements stay in the same order. Use reverse() to do the reverse.

use Module LIST
use Module

Imports some semantics into the current package from the named module, generally by aliasing certain subroutine or variable names into your package. It is exactly equivalent to

    BEGIN { require Module; import Module LIST; }

except that Module must be a bareword.

If the first argument to use is a number, it is treated as a version number instead of a module name. If the version of the Perl interpreter is less than VERSION, then an error message is printed and Perl exits immediately. This is often useful if you need to check the current Perl version before useing library modules that have changed in incompatible ways from older versions of Perl. (We try not to do this more than we have to.)

The BEGIN forces the require and import() to happen at compile time. The require makes sure the module is loaded into memory if it hasn't been yet. The import() is not a builtin--it's just an ordinary static method call into the ``Module'' package to tell the module to import the list of features back into the current package. The module can implement its import() method any way it likes, though most modules just choose to derive their import() method via inheritance from the Exporter class that is defined in the Exporter module. See Exporter. If no import() method can be found then the error is currently silently ignored. This may change to a fatal error in a future version.

If you don't want your namespace altered, explicitly supply an empty list:

    use Module ();

That is exactly equivalent to

    BEGIN { require Module }

If the VERSION argument is present between Module and LIST, then the use will call the VERSION method in class Module with the given version as an argument. The default VERSION method, inherited from the Universal class, croaks if the given version is larger than the value of the variable $Module::VERSION. (Note that there is not a comma after VERSION!)

Because this is a wide-open interface, pragmas (compiler directives) are also implemented this way. Currently implemented pragmas are:

    use integer;
    use diagnostics;
    use sigtrap qw(SEGV BUS);
    use strict  qw(subs vars refs);
    use subs    qw(afunc blurfl);

Some of these these pseudo-modules import semantics into the current block scope (like strict or integer, unlike ordinary modules, which import symbols into the current package (which are effective through the end of the file).

There's a corresponding ``no'' command that unimports meanings imported by use, i.e., it calls unimport Module LIST instead of import().

    no integer;
    no strict 'refs';

If no unimport() method can be found the call fails with a fatal error.

See perlmod for a list of standard modules and pragmas.

utime LIST

Changes the access and modification times on each file of a list of files. The first two elements of the list must be the NUMERICAL access and modification times, in that order. Returns the number of files successfully changed. The inode modification time of each file is set to the current time. This code has the same effect as the ``touch'' command if the files already exist:

    $now = time;
    utime $now, $now, @ARGV;
values HASH

Returns a list consisting of all the values of the named hash. (In a scalar context, returns the number of values.) The values are returned in an apparently random order. The actual random order is subject to change in future versions of perl, but it is guaranteed to be the same order as either the keys() or each() function would produce on the same (unmodified) hash.

Note that you cannot modify the values of a hash this way, because the returned list is just a copy. You need to use a hash slice for that, since it's lvaluable in a way that values() is not.

    for (values %hash)      { s/foo/bar/g }   # FAILS!
    for (@hash{keys %hash}) { s/foo/bar/g }   # ok

As a side effect, calling values() resets the HASH's internal iterator. See also keys(), each(), and sort().


Treats the string in EXPR as a vector of unsigned integers, and returns the value of the bit field specified by OFFSET. BITS specifies the number of bits that are reserved for each entry in the bit vector. This must be a power of two from 1 to 32. vec() may also be assigned to, in which case parentheses are needed to give the expression the correct precedence as in

    vec($image, $max_x * $x + $y, 8) = 3;

Vectors created with vec() can also be manipulated with the logical operators |, &, and ^, which will assume a bit vector operation is desired when both operands are strings. See perlop.

The following code will build up an ASCII string saying 'PerlPerlPerl'. The comments show the string after each step. Note that this code works in the same way on big-endian or little-endian machines.

    my $foo = '';
    vec($foo,  0, 32) = 0x5065726C;     # 'Perl'
    vec($foo,  2, 16) = 0x5065;         # 'PerlPe'
    vec($foo,  3, 16) = 0x726C;         # 'PerlPerl'
    vec($foo,  8,  8) = 0x50;           # 'PerlPerlP'
    vec($foo,  9,  8) = 0x65;           # 'PerlPerlPe'
    vec($foo, 20,  4) = 2;              # 'PerlPerlPe'   . "\x02"
    vec($foo, 21,  4) = 7;              # 'PerlPerlPer'
                                        # 'r' is "\x72"
    vec($foo, 45,  2) = 3;              # 'PerlPerlPer'  . "\x0c"
    vec($foo, 93,  1) = 1;              # 'PerlPerlPer'  . "\x2c"
    vec($foo, 94,  1) = 1;              # 'PerlPerlPerl'
                                        # 'l' is "\x6c"

To transform a bit vector into a string or array of 0's and 1's, use these:

    $bits = unpack("b*", $vector);
    @bits = split(//, unpack("b*", $vector));

If you know the exact length in bits, it can be used in place of the *.


Behaves like the wait(2) system call on your system: it waits for a child process to terminate and returns the pid of the deceased process, or -1 if there are no child processes. The status is rketurned in $?. Note that a return value of -1 could mean that child processes are being automatically reaped, as described in perlipc.

waitpid PID,FLAGS

Waits for a particular child process to terminate and returns the pid of the deceased process, or -1 if there is no such child process. On some systems, a value of 0 indicates that there are processes still running. The status is returned in $?. If you say

    use POSIX ":sys_wait_h";
    do { 
        $kid = waitpid(-1,&WNOHANG);
    } until $kid == -1;

then you can do a non-blocking wait for all pending zombie processes. Non-blocking wait is available on machines supporting either the waitpid(2) or wait4(2) system calls. However, waiting for a particular pid with FLAGS of 0 is implemented everywhere. (Perl emulates the system call by remembering the status values of processes that have exited but have not been harvested by the Perl script yet.)

Note that on some systems, a return value of -1 could mean that child processes are being automatically reaped. See perlipc for details, and for other examples.


Returns TRUE if the context of the currently executing subroutine is looking for a list value. Returns FALSE if the context is looking for a scalar. Returns the undefined value if the context is looking for no value (void context).

    return unless defined wantarray;    # don't bother doing more
    my @a = complex_calculation();
    return wantarray ? @a : "@a";
warn LIST

Produces a message on STDERR just like die(), but doesn't exit or throw an exception.

If LIST is empty and $@ already contains a value (typically from a previous eval) that value is used after appending "\t...caught" to $@. This is useful for staying almost, but not entirely similar to die().

If $@ is empty then the string "Warning: Something's wrong" is used.

No message is printed if there is a $SIG{__WARN__} handler installed. It is the handler's responsibility to deal with the message as it sees fit (like, for instance, converting it into a die()). Most handlers must therefore make arrangements to actually display the warnings that they are not prepared to deal with, by calling warn() again in the handler. Note that this is quite safe and will not produce an endless loop, since __WARN__ hooks are not called from inside one.

You will find this behavior is slightly different from that of $SIG{__DIE__} handlers (which don't suppress the error text, but can instead call die() again to change it).

Using a __WARN__ handler provides a powerful way to silence all warnings (even the so-called mandatory ones). An example:

    # wipe out *all* compile-time warnings
    BEGIN { $SIG{'__WARN__'} = sub { warn $_[0] if $DOWARN } }
    my $foo = 10;
    my $foo = 20;          # no warning about duplicate my $foo,
                           # but hey, you asked for it!
    # no compile-time or run-time warnings before here
    $DOWARN = 1;

    # run-time warnings enabled after here
    warn "\$foo is alive and $foo!";     # does show up

See perlvar for details on setting %SIG entries, and for more examples. See the Carp module for other kinds of warnings using its carp() and cluck() functions.

write EXPR

Writes a formatted record (possibly multi-line) to the specified FILEHANDLE, using the format associated with that file. By default the format for a file is the one having the same name as the filehandle, but the format for the current output channel (see the select() function) may be set explicitly by assigning the name of the format to the $~ variable.

Top of form processing is handled automatically: if there is insufficient room on the current page for the formatted record, the page is advanced by writing a form feed, a special top-of-page format is used to format the new page header, and then the record is written. By default the top-of-page format is the name of the filehandle with ``_TOP'' appended, but it may be dynamically set to the format of your choice by assigning the name to the $^ variable while the filehandle is selected. The number of lines remaining on the current page is in variable $-, which can be set to 0 to force a new page.

If FILEHANDLE is unspecified, output goes to the current default output channel, which starts out as STDOUT but may be changed by the select() operator. If the FILEHANDLE is an EXPR, then the expression is evaluated and the resulting string is used to look up the name of the FILEHANDLE at run time. For more on formats, see perlform.

Note that write is NOT the opposite of read(). Unfortunately.


The transliteration operator. Same as tr///. See perlop.

Linux Will Become Indistinguishable From Unix

Finally, Forrester predicts that by 2004, Linux and proprietary Unix will have so much in common that many binaries will run on either platform.

"IBM, HP and Sun are grafting Linux interoperability features onto upcoming releases of AIX, HP-UX and Solaris -- and engineers from SGI, HP and IBM are working on the Trillian project to solve Linux's scalability problems," the report concludes.

[Jan 3, 2000] ZDNet Not a Monopoly, Marketing -- John C. Dvorak PC Magazine Opinions -- I believe that the autor is wrong and Microsoft does not control the PC as a platform. But Microsoft is a very influential player in this game (probably second after Intel) and here the article attract attention to this subtle fact.

Microsoft is not a monopoly; it just pretends to be one. In fact, what's gotten the company into trouble is its scheme to cover up the fact that the PC is a proprietary platform designed and owned by Microsoft. Windows is part of a proprietary platform and competes with other pure platforms, including Mac and Sun's Solaris. Why else would Scott McNealy be so obsessed with Microsoft?

Microsoft's model for marketing a proprietary PC (which I'll call the Microsoft Windows PC) is unusual, because Microsoft doesn't manufacture the hardware. The concept is similar to the fab-less semiconductor company. Microsoft does control the specifications of the computers and essentially outsources the manufacturing of the computers on a no-fee basis. This is a remarkably generous approach. The company expects that this generosity be rewarded with some modest amount of loyalty. Why should Microsoft put all this effort into the design (for example, PC-100 specifications) if a company is going to put Linux on the PC? Use a new legacy-free box or something else for that.

It's for marketing purposes that this proprietary Microsoft Windows PC platform is not portrayed as such. Microsoft is playing into the sentimental notion that the PC itself is an open platform that offers more choices. Third-party development and faux competition with Microsoft was encouraged to deceive the buying public.

With the PC, Microsoft took control of the platform immediately and is largely responsible for its development. The DOJ testimony that Microsoft was pushing Intel around reflects this fact. IBM got early credit for the platform, but when IBM rolled out its PS/2 machines and the Micro Channel, IBM found Microsoft owned the platform. Once Windows fully arrived, Microsoft took brutal control.

This way of looking at Microsoft and Windows explains everything, including Microsoft's recent whining — especially about innovation. To many of us Microsoft seems to have made no innovations that weren't borrowed or bought. But if you throw in the hardware part of the equation, you'll find things such as the USB port and other true innovations. Microsoft's annual WinHEC conference addresses the hardware aspect of the Windows platform. Why would such a conference even exist if Microsoft weren't in full control of hardware specifications?

Seeing the Windows PC as a proprietary platform also explains why Microsoft would want Netscape out of the picture. I'm certain that nobody at Netscape visualized the situation accurately. They obviously believed the Microsoft marketing nonsense and made bad assumptions. By siding with Sun and making noise about having a Net OS running on the Microsoft Windows PC hardware, Netscape violated the proprietary nature of the Microsoft Windows PC.

Microsoft owns the specifications and essentially licenses them on a no-fee basis, so the company feels no obligation to let other companies do whatever they want on the system, which would be like going into a fancy restaurant and setting up your own hot- dog stand. Once Microsoft decided to shut Netscape out, it had to go around and remind the gratis licensees (Dell, Compaq, and others) of their obligations as manufacturers of the Microsoft machine! These companies make money off Microsoft's hard work — at the behest of Microsoft. Seen this way, the Microsoft "threats" to pull the OS from any company bundling Netscape were reasonable.

The most laughable irony is that Microsoft has marketed around the fact that the Microsoft Windows PC is a proprietary computer. The marketing machine should have said: "Hey, this whole thing is nonsense, since we own a closed proprietary system. It was only for the purposes of marketing that we made it appear to be open, so we could sucker people into buying our software and fool them into believing they actually had a real choice. Marketing, marketing, marketing." The fact that other operating systems can run on the Microsoft Windows PC is actually amazing. But the fact that few people use these other systems is no surprise.

Seen in this light, Microsoft is no more a monopoly than any other company selling a single product in a complex marketplace. Unfortunately, the foundation of Microsoft's success — an overly complex marketing scheme — is what led to this recent humiliation.


FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available in our efforts to advance understanding of environmental, political, human rights, economic, democracy, scientific, and social justice issues, etc. We believe this constitutes a 'fair use' of any such copyrighted material as provided for in section 107 of the US Copyright Law. In accordance with Title 17 U.S.C. Section 107, the material on this site is distributed without profit exclusivly for research and educational purposes.   If you wish to use copyrighted material from this site for purposes of your own that go beyond 'fair use', you must obtain permission from the copyright owner. 

ABUSE: IPs or network segments from which we detect a stream of probes might be blocked for no less then 90 days. Multiple types of probes increase this period.  


Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy


War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes


Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law


Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least

Copyright © 1996-2016 by Dr. Nikolai Bezroukov. was created as a service to the UN Sustainable Development Networking Programme (SDNP) in the author free time. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License.

The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to make a contribution, supporting development of this site and speed up access. In case is down you can use the at


The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the author present and former employers, SDNP or any other organization the author may be associated with. We do not warrant the correctness of the information provided or its fitness for any purpose.

Created June 1, 1998; Last modified: February 19, 2014