File expressions in bash

There is quite a lot to say about testing and one of the most common tasks is checking files on the filesystem or if a directory is available or has some rights. So, imagine a script that has to write some data in a file inside a directory: first, we should check whether the directory exists, then if we can write into it, and finally if there is no name collision between the file we are going to open for writing and an already existing file. So let's have a look at which operators we use to execute some tests on files and devices and remember that they return true if the condition is met:

 ls test-files.sh 
test-files.sh  

We just verified that the file test-files.sh exists since ls shows it:

 if [ -e test-files.sh ] ; then 
echo "Yes, this is a file!" ; fi
Yes, this is a file device!  

Our test confirms it with a nice message.

Let's verify now that a file named aaaaa is not present in our current directory:

 lsaaaaa
ls: cannot access 'aaaaa': No such file or directory 

OK, there is no file with such a name; let us do a test:

 if [ -e aaaaa ] ; then echo "Yes, this is a file!"; 
else 
echo "There is not such a file!" ; fi
There is not such a file!  

Well, as you can see, we used a semicolon to divide the different parts of the statement. In a script, we would have seen the following:

#!/bin/bash
if [ -e aaaaa ]
then
echo "Yes, this is a file!"
else
echo "There is not such a file!"
fi

Each single command must be properly terminated either by a new line or a ;. Each chunk of code delimited by a ; will be executed before the following without the need for a new line.

 if [ -b /dev/nvme0n1p1 ] ; 
then 
echo "Yes, this is a block device!" ; fi
Yes, this is a block device!  

 if [ -d test ] ; 
then echo "Yes, this is a directory!" ; 
else echo "There is not such a directory!" ; fi
Yes, this is a directory!  
 if [ -f /dev/tty7 ] ; 
then echo "Yes, this is a regular file!" ; 
else echo "There is not a regular file!" ; fi
There is not a regular file!  

Well, this is a file that represents a terminal, so it is clearly not a regular file as test.file could be:

 touch test.file    
 if [ -f test.file ] ; 
then echo "Yes, this is a regular file!" ; 
else echo "There is not a regular file!" ; fi
Yes, this is a regular file!  
 if [ -c /dev/tty7 ] ; 
then echo "Yes, this is a character file!" ; 
else echo "There is not a character file!" ; fi
Yes, this is a character file!  
 if [ -s test.file ] ; 
then echo "Yes, the size of this file is not 0!" ; 
else echo "The size of this file is 0!" ; fi
The size of this file is 0!  

Well, we just touched the file, so we created it with 0 byte size. Let's fill it with a character:

 echo 1 >>test.file

And now, let's repeat the test:

 if [ -s test.file ] ; 
then echo "Yes, the size of this file is not 0!" ; 
else echo "The size of this file is 0!" ; fi
Yes, the size of this file is not 0!  
 if [ -g test ] ; 
then echo "Yes, this dir has a sgid bit" ; 
else echo "No sgid bit on this dir" ; fi
No sgid bit on this dir  

And now:

 chmodg+s test
 if [ -g test ] ; 
then echo "Yes, this dir has a sgid bit" ; 
else echo "No sgid bit on this dir" ; fi
Yes, this dir has a sgid bit  
 if [ -G test.file ] ; 
then echo "Yes, this file has your same group owner" ; 
else echo "No the group owner is not the same of yours" ; fi
Yes, this file has your same group owner  

And now on a directory:

 if [ -G test ] ; 
then echo "Yes, this file has your same group owner" ; 
else echo "No the group owner is not the same of yours" ; fi
Yes, this file has your same group owner  

Let's double-check changing the group owner of test.file:

 su
Password: 
root:# chgrp root test.file
root:# ls -lahtest.file
-rw-r--r-- 1 zarrelli root 2 Feb  6 18:23 test.file
root:# exit
exit
 if [ -G test.file ] ; 
then echo "Yes, this file has your same group owner" ; 
else echo "No the group owner is not the same of yours" ; fi
No the group owner is not the same of yours  
if [ -O test.file ] ; 
then echo "Yes, you are the owner" ; 
else echo "No you are not the owner" ; fi
Yes, you are the owner
 ls -lahtest.file
-rw-r--r-- 1 zarrellizarrelli 2 Feb  6 18:23 test.file  
 if [ -N userinput-or.sh ] ; 
then echo "Yes, it has been modified since last read" ; 
else echo "No modifications since last read " ; fi
No modifications since last read   

OK, the files seems to have not been modified lately, so it is time to modify it:

 echo 1 >> userinput-or.sh 
 if [ -N userinput-or.sh ] ; 
then echo "Yes, it has been modified since last read" ; 
else echo "No modifications since last read " ; fi
Yes, it has been modified since last read  

That's it. Remember that in all the tests when we say that the test is true when the condition is verified, we imply a second condition that is the file must exist. So in this case, we would say, it is verified if the file exists and has not been modified from last read. Also remember that in Unix everything is a file, so a directory.

zarrelli:$ su
Password: 
root:# chown root test.file
root:# ls -lahtest.file
-rw-r--r-- 1 root zarrelli 2 Feb  6 18:23 test.file
root:# chmod +s test.file
root:# ls -lahtest.file
-rwSr-Sr-- 1 root zarrelli 2 Feb  6 18:23 test.file
root:# exit
exit
 if [ -u test.file ] ; 
then echo "Yes, it has the suid bit flagged" ; 
else echo "No suid bit found" ; fi  
 chmod +t test
 if [ -k test ] ; 
then echo "Yes, it has the sticky bit set" ; 
else echo "No sticky bit set" ; fi
Yes, it has the sticky bit set  
 if [ -r test.file ] ; 
then echo "Yes, this user can read the file" ; 
else echo "No this user cannot read the file" ; fi
Yes, this user can read the file  

So, the user can read the file, let's check the following:

ls -lahtest.file
-rwSr-Sr-- 1 root zarrelli 2 Feb  6 18:23 test.file  

Oh, well, the file is owned by root and root has read access, so why was the test successful if the read is granted to root? Simple:

 su
Password: 
root:# chmodog-r test.file
root:# exit
exit
 if [ -r test.file ] ; 
then echo "Yes, this user can read the file" ; 
else echo "No this user cannot read the file" ; fi
No this user cannot read the file  

What happened? The first time we tried the test the owner was root, but the user zarrelli was still able to read the file through group permission and other permission. So, clearing those bits made the file readable only by the root user, no one else.

 if [ -w test.file ] ; 
then echo "Yes, this user can write to the file" ; 
else echo "No this user cannot write to the file" ; fi
No this user cannot write to the file  

Interesting, let's have a look at the file:

 ls -lahtest.file
-rw---S--- 1 root zarrelli 2 Feb  6 18:23 test.file  

Indeed, only the root user can write to it. Would you like to try and fix the issue then run the test again?

 if [ -x test.file ] ; 
then echo "Yes, this user can execute it" ; 
else echo "No this user cannot execute it" ; fi
No this user cannot execute it  

Let's see what the access permissions on the file are:

ls -lah test.file
-rw---S--- 1 root zarrelli 2 Feb  6 18:23 test.file  

So no execute bit for the user. Now, let's test a directory:

 if [ -x test ] ; 
then echo "Yes, this user can execute it" ; 
else echo "No this user cannot execute it" ; fi
Yes, this user can execute it  

Interesting, time to see the permissions on the directory:

 ls -lah test
total 8.0K
drwxr-sr-t 2 zarrellizarrelli 4.0K Feb  6 18:12 .
drwxr-xr-x 3 zarrellizarrelli 4.0K Feb  7 08:12 ..  

What are those dots and double dots? Let's have a closer look:

ls -lai
total 8
5900830 drwxr-sr-t 2 zarrellizarrelli 4096 Feb  6 18:12 .
5899440 drwxr-xr-x 3 zarrellizarrelli 4096 Feb  7 08:12 ..  

Keep in mind the first column. These are the inode numbers related to .. and..:

zarrelli@:~$ cd ..
zarrelli@:~$ ls -lai
total 36
5899440drwxr-xr-x 3 zarrellizarrelli 4096 Feb  7 08:12 .
5899435 drwxr-xr-x 3 zarrellizarrelli 4096 Feb  7 20:47 ..
5900830 drwxr-sr-t 2 zarrellizarrelli 4096 Feb  6 18:12 
test
5899311 -rw---S--- 1 root     zarrelli    2 Feb  6 18:23 
test.file
5899447 -rwxr--r-- 1 zarrellizarrelli  319 Feb  5 11:42 
test-files-not.sh
5899450 -rwxr--r-- 1 zarrellizarrelli  317 Feb  5 11:21 
test-files.sh
5898796 -rw-r--r-- 1 zarrellizarrelli    0 Feb  7 08:00 
test.modified
5899448 -rwxrwxr-x 1 zarrellizarrelli  352 Feb  5 12:31 
userinput-and.sh
5899449 -rwxr-xr-x 1 zarrellizarrelli  190 Feb  5 12:41 
userinput-and-simple.sh
5899444 -rwxrwxr-x 1 zarrellizarrelli  305 Feb  7 08:07 
userinput-or.sh  

The inode of . inside the test directory has the value of 5900830, so now we go up one directory, and we can see that the test directory has an inode value of 5900830. So, we can safely say that .points to the directory we are in. And what about ..? Look at the value of .in the parent directory, it is 5899440. Now look inside the test directory to the value of .., it is 5899440, and so we can safely say that..points to the parent directory since both point to the same inode.

Briefly, to understand what relates an inode to a file, we can say that in a Unix style file system, an inode is a metadata structure describing file and directories attributes, such as type timestamp, size, access rights, links count, and pointers to the disk block holding the data that make up a file or directory content. Each inode number is practically an index that allows the kernel to access a file or directory, its content and attributes, such as an index in an array. And actually, you can know quite a bit of a file if you know how to look at it:

 stat test
  File: test
  Size: 4096      Blocks: 8          IO Block: 4096   
  directory
Device: fd01h/25025aInode: 5900830     Links: 2
Access: (3755/drwxr-sr-t)  Uid: ( 1200/zarrelli)   Gid: ( 1200/zarrelli)
Access: 2017-02-06 18:12:53.376827639 +0000
Modify: 2017-02-06 18:12:53.376827639 +0000
Change: 2017-02-07 19:26:15.936253432 +0000
 Birth: -  

So, what we can say is that something pointing to the same inode number is pointing to the same data structure, the same file or directory, and that is what links the .. and .to the representation of the parent and local directory as we proved by following the inode numbers.

So, to make it easy, we can say that the soft link is a pointer by name to a file, whereas a hard link is a pointer by inode. Let's see some differences in play starting with a soft link:

 ln -s test.filenew.test.file
zarrelli@:~$ ls -lah | grep new
lrwxrwxrwx 1 zarrellizarrelli    9 Feb  7 21:48 new.test.file ->test.file  

Let's cat the link:

 su
Password: 
root:# chmoda+rtest.file
root:# exit
exit
 cat new.test.file
1  

Now, let's remove the original file:

 rmtest.file

And verify if we can access the content through the link:

 cat new.test.file
cat: new.test.file: No such file or directory 

The problem is clear with ls:

 ls -lah
total 32K
drwxr-xr-x 3 zarrellizarrelli 4.0K Feb  7 22:06 .
drwxr-xr-x 3 zarrellizarrelli 4.0K Feb  7 22:02 ..
lrwxrwxrwx 1 zarrellizarrelli    9 Feb  7 21:48 
new.test.file ->test.file
drwxr-sr-t 2 zarrellizarrelli 4.0K Feb  6 18:12 
test
-rwxr--r-- 1 zarrellizarrelli  319 Feb  5 11:42 
test-files-not.sh
-rwxr--r-- 1 zarrellizarrelli  317 Feb  5 11:21 
test-files.sh
-rw-r--r-- 1 zarrellizarrelli    0 Feb  7 08:00 
test.modified
-rwxrwxr-x 1 zarrellizarrelli  352 Feb  5 12:31 
userinput-and.sh
-rwxr-xr-x 1 zarrellizarrelli  190 Feb  5 12:41 
userinput-and-simple.sh
-rwxrwxr-x 1 zarrellizarrelli  305 Feb  7 08:07 
userinput-or.sh  

The link is still there, but the original file is gone, so when the OS tries to reach it, it fails. Let us recreate the original file and the link:

 rmnew.test.file
 rmnew.test.file
 echo 1 >test.file
 ln -s test.filenew.test.file  

Now, let's link across the /boot filesystem. First, let's check that /boot is mounted on its own partition and filesystem:

 mount  | grep boot
/dev/nvme0n1p1 on /boot type ext2 (rw,relatime,block_validity,barrier,user_xattr,acl) 

OK, it is really another filesystem, so let's soft link:

 su
Password:     
root:# ln -s test.file /boot/boot.test.file  

And access the link:

root:# cat /boot/boot.test.file
cat: /boot/boot.test.file: No such file or directory  

Well, something has gone wild. What is happening? Have a look with ls -lah:

root:# ls -lah /boot/boot.test.file
lrwxrwxrwx 1 root root 9 Feb  7 22:19 /boot/boot.test.file 
->test.file  

Well, the link points to test.file in /boot even though we linked from another directory. We need an absolute reference:

root:# ln -s /home/zarrelli/test.file /boot/new.test.file
root:# cat /boot/new.test.file  

And now it works. Finally, let's see what happens if we try to link a directory:

 ln -s test new.test  

We linked new.test to the test directory and now just check that the test directory is empty:

 ls -lah test
total 8.0K
drwxr-sr-t 2 zarrellizarrelli 4.0K Feb  7 22:29 .
drwxr-xr-x 3 zarrellizarrelli 4.0K Feb  7 22:26 ..  

Now, let's create a file using the link:

 echo 2 >new.test/testing
 cat test/testing 
2  

And let's see what is in test:

 cat test/testing 
2  

Here we are; we can reach the data inside test using the new.test soft link.

Now it is time to hard link across filesystems:

 su
Password: 
root:# ln  /home/zarrelli/test.file /boot/hard.test.file
ln: failed to create hard link '/boot/hard.test.file' =>'/home/zarrelli/test.file': Invalid cross-device link  

No way! We cannot reference with a hard link across filesystems; the inode restriction is preventing us from doing it.

Now, let's try to link a directory:

 ln test hard.test
ln: test: hard link not allowed for directory  

Again, no good to go. Now, let us try to hard link in the same filesystem:

 lntest.filehard.test.file  

No problem, but let's have a look at the inodes:

 ls -lai
total 40
5899440 drwxr-xr-x 3 zarrellizarrelli 4096 Feb  7 22:35 .
5899435 drwxr-xr-x 3 zarrellizarrelli 4096 Feb  7 22:33 ..
5899465 -rw-r--r-- 2 zarrellizarrelli    2 Feb  7 22:11 
hard.test.file
5899355 lrwxrwxrwx 1 zarrellizarrelli    4 Feb  7 22:26 
new.test -> test
5900839 lrwxrwxrwx 1 zarrellizarrelli    9 Feb  7 22:12 
new.test.file ->test.file
5900830 drwxr-sr-t 2 zarrellizarrelli 4096 Feb  7 22:31 
test
5899465 -rw-r--r-- 2 zarrellizarrelli    2 Feb  7 22:11 
test.file
5899447 -rwxr--r-- 1 zarrellizarrelli  319 Feb  5 11:42 
test-files-not.sh
5899450 -rwxr--r-- 1 zarrellizarrelli  317 Feb  5 11:21 
test-files.sh
5898796 -rw-r--r-- 1 zarrellizarrelli    0 Feb  7 08:00 
test.modified
5899448 -rwxrwxr-x 1 zarrellizarrelli  352 Feb  5 12:31 
userinput-and.sh
5899449 -rwxr-xr-x 1 zarrellizarrelli  190 Feb  5 12:41 
userinput-and-simple.sh
5899444 -rwxrwxr-x 1 zarrellizarrelli  305 Feb  7 08:07 
userinput-or.sh  

The hard link points to the same inode of the original file, the soft link does not. Now remove the original file again and try to cat the hard and soft link:

 rmtest.file
 cat new.test.file
cat: new.test.file: No such file or directory
 cat hard.test.file
1  

As we expected, the soft link failed because there is no filename to point to, the hard link succeeded because the inode is still there:

ls -lahi
total 36K
5899440 drwxr-xr-x 3 zarrellizarrelli 4.0K Feb  7 22:40 .
5899435 drwxr-xr-x 3 zarrellizarrelli 4.0K Feb  7 22:33 ..
5899465 -rw-r--r-- 1 zarrellizarrelli    2 Feb  7 22:11 
hard.test.file
5899355 lrwxrwxrwx 1 zarrellizarrelli    4 Feb  7 22:26 
new.test -> test
5900839 lrwxrwxrwx 1 zarrellizarrelli    9 Feb  7 22:12 
new.test.file ->test.file
5900830 drwxr-sr-t 2 zarrellizarrelli 4.0K Feb  7 22:31 
test
5899447 -rwxr--r-- 1 zarrellizarrelli  319 Feb  5 11:42 
test-files-not.sh
5899450 -rwxr--r-- 1 zarrellizarrelli  317 Feb  5 11:21 
test-files.sh
5898796 -rw-r--r-- 1 zarrellizarrelli    0 Feb  7 08:00 
test.modified
5899448 -rwxrwxr-x 1 zarrellizarrelli  352 Feb  5 12:31 
userinput-and.sh
5899449 -rwxr-xr-x 1 zarrellizarrelli  190 Feb  5 12:41 
userinput-and-simple.sh
5899444 -rwxrwxr-x 1 zarrellizarrelli  305 Feb  7 08:07 
userinput-or.sh  

A quick rule of thumb is do not use soft link to reference frequently accessed files, such as web pages, use them for config files for instance, as they are just read at the startup. Soft links are slow. Hard links are good for referencing files and preserve their content despite what happens to the origin:

 mkfifomyfifo  

Now, let's open a second terminal and issue, in the same directory, the command:

 cat myfifo  

The process will hang waiting for something to read. Now, let's go back to the first terminal and write something to the named pipe:

 echo hello >myfifo  

Now back to the second terminal to check what happened:

 cat myfifo
hello  

We will see more on named pipes in one of the next chapters, now we will just check if myfifo is really a named pipe:

 if [ -p myfifo ] ; 
then echo "Yes, it is a named pipe" ; 
else echo "No it is not a pipe" ; fi
Yes, it is a named pipe  

     if [ -S /tmp/OSL_PIPE_1000_SingleOfficeIPC_39e ] ; then echo "Yes, it is a named pipe" ; else echo "No it is not a pipe" ; fi
Yes, it is a named pipe

And we can double-check looking for and in the property of the file as listed by ls:

 ls -lah /tmp/OSL_PIPE_1000_SingleOfficeIPC_39e 
srwxr-xr-x 1 zarrellizarrelli 0 Feb 12 09:02 /tmp/OSL_PIPE_1000_SingleOfficeIPC_39e

We can see an s character at the beginning of the permissions list, and this is what tells has that this file is exactly a socket, as we expected.

 if [ -t 1 ] ; 
then echo "Yes, it is associated to a terminal" ; 
else echo "No it is not associated to a terminal" ; fi
Yes, it is associated to a terminal  

Need to double-check it? Simple, since the output of our command issued in the current shell has been printed to our monitor, which is connected to the terminal.

 touch other_file ; 
for i in {1..10}; do : ; done ; touch file; 
if [ file -ntother_file ] ; 
then echo "Yes, file is newer then other_file" ; 
else echo "No file is not newer than other_file" ; fi
Yes, file is newer then other_file  

So, what did we do? We simply chained some commands, and since other_file must be the older piece, we started off creating it. Then, we setup a simple "for" loop iterating between 1 and 10 doing nothing, as implied by the double colon, since we had to let some time pass before creating the newer file. Passed 10 iterations we created a new file and compared the two. One thing that appears interesting in this example is the use of:

{1..10}  

This is a construct available since Bash newer than 3.0. Let us quickly set up a range writing the starting number and the ending one. From Bash newer than 4.0, we can also define a range with increments, in the form of:

{start..end..step}  

Like in the following example:

 touch other_file ; 
for i in {1..120..2}; do if [ $(($i%5)) -eq 0 ] ; 
then echo "Waiting...cycle $i" ; fi ; sleep 1 ; done ; 
touch file; if [ file -ntother_file ] ; 
then echo "Yes, file is newer then other_file" ; 
else echo "No file is not newer than other_file" ; fi
Waiting...cycle 5
Waiting...cycle 15
Waiting...cycle 25
Waiting...cycle 35
Waiting...cycle 45
Waiting...cycle 55
Waiting...cycle 65
Waiting...cycle 75
Waiting...cycle 85
Waiting...cycle 95
Waiting...cycle 105
Waiting...cycle 115
Yes, file is newer then other_file  

Well, added few things here: the cycle now goes from 1 to 120 in steps of 2 and prints out a message only if the cycle number can be divided by 5, so we will not clutter the screen. Finally, we wait for one sec at each cycle using the sleep command to ensure that at the end of the cycle we spent 60 seconds before creating the last file and making the comparison.

We can also modify the date of a file using a specific date, even back in the past, using touch with the format -t YYMMDDHHmm:
 ls -lahtest.file
-rw-r--r-- 3 zarrellizarrelli 0 Feb 12 14:56 test.file
touch -t 8504251328 test.file
 ls -lahtest.file
-rw-r--r-- 3 zarrellizarrelli 0 Apr 25 1985 test.file
zarrelli:~/$ if [ userinput-or.sh -otother_file ] ; 
then echo "Yes, the first file is older than the second" ; 
else echo "No the first file is not older than the second" ; fi  

And indeed:

zarrelli:~/$ ls -laht userinput-or.sh other_file
-rw-r--r-- 1 zarrellizarrelli   0 Feb 12 14:16 other_file
-rwxrwxr-x 1 zarrellizarrelli 305 Feb  7 08:07 userinput-or.sh  

Now just touch the userinput-or.sh:

 if [ userinput-or.sh -otother_file ] ; 
then echo "Yes, the first file is older than the second" ; 
else echo "No the first file is not older than the second" ; fi
No the first file is not older than the second  
rmtest.file
 rmnew.test.file
 touch test.file
lntest.filenew.test.file
lntest.fileother.new.test.file
 if [ new.test.file -efother.new.test.file ] ; 
then echo "Yes, the files share the same inode number and device" ; else echo "No the files do not share the same inode number and device" ; fi
Yes, the files share the same inode number and device  

Now let's double-check:

 lls -laihtest.fileother.new.test.fileother
.new.test.file
5900839 -rw-r--r-- 3 zarrellizarrelli 0 Feb 12 14:56 other.new.test.file
5900839 -rw-r--r-- 3 zarrellizarrelli 0 Feb 12 14:56 other.new.test.file
5900839 -rw-r--r-- 3 zarrellizarrelli 0 Feb 12 14:56 
test.file  

All three files share the same inode and, since the inode is a metastructure of a file system, a single file system.

We are done with the file comparison, but there is some more that we have to see, for instance how we can test integers since they are quite a common presence in all the script we see around the Internet.


Top Visited
Switchboard
Latest
Past week
Past month

NEWS CONTENTS

Old News ;-)

Recommended Links

Google matched content

Softpanorama Recommended

Top articles

Sites



Etc

Society

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

Quotes

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

Bulletin:

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

History:

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 Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D


Copyright © 1996-2018 by Dr. Nikolai Bezroukov. www.softpanorama.org was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) in the author free time and without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. 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 softpanorama.org is down you can use the at softpanorama.info

Disclaimer:

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.

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.

Last modified: September, 28, 2017