Softpanorama

May the source be with you, but remember the KISS principle ;-)
Home Switchboard Unix Administration Red Hat TCP/IP Networks Neoliberalism Toxic Managers
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and  bastardization of classic Unix

Recursive uploading of directories via FTP

News

NcFTP Recommended Links Scripting FTP sessions FTP Filesystems Commands for translating files from DOS to Unix FTP Security
LFTP FileZilla WinSCP NetDrive      
Curl wget rsync   Admin Horror Stories Humor Etc

While for downloading directories via FTP there are many tools, for recursive uploading via FTP only few tools exists.  Windows 7 supports FTP filesystem natively -- you can connect to ftp site in such a way that it will be mapped as a drive.  NetDrive provide this capability for Windows XP.

If we are talking about command line tool the best is probably  ncftpput  (see NcFTP )

BTW regular, "classic" ftp client is also scriptable via I/O redirection. 

Other options are discussed in the Stack Overflow post recursion - Recursively PUT files to a remote server using FTP

Sep 10, 2010 | Stack Overflow

I'm currently in a situation where I have very limited access to a server, but need to upload and download a significant amount of files contained within a single directory structure. I don't have SSH access, so I can't use SCP - and rsync isn't an option either unfortunately.

I'm currently using ncftpput, which is great but seems to be quite slow (in spite of a fast connection).

Is there an alternative / better method I could look into?

(Please accept my apologies if this has been covered, I did a quick search prior to posting but didn't find anything that specifically answered my question)

Answers

Try using LFTP: http://lftp.yar.ru/

or YAFC: http://yafc.sourceforge.net/index.php


2

for ncftp - are you using "put -R" command to do a recursive directory upload? – DmitryK Sep 10 '09 at 2:38

I am indeed - I think part of the problem is FTP is quite antiquated.. so there might not be an ideal solution – codeinthehole Sep 10 '09 at 3:29

If you have a good connection, I would recommend mounting the ftp server via the GNOME or KDE file managers, or else using CurlFtpFS. Then you can treat it like just another folder.


This is a horrible answer. There is no way that doing this would be faster than FTP, and it's a lot more risky, especially with high volumes of data, as it doesn't support resume on interrupt. And if he doesn't have access to SSH, how is he going to configure it for mounting? – Benubird Mar 15 '13 at 11:49




No server configuration is required. The server is already configured for FTP. And the point isn't to make things faster, it's to make them easier. After mounting with CurlFtpFS, once could use standard unix utils like cp and rsync. I did say it works best with a good connection. – Ryan Thompson Mar 15 '13 at 15:27

I'm not familiar with ncftpput. For non-interactive FTP, I've always used the Perl Net::FTP module -- http://perldoc.perl.org/Net/FTP.html

This will be faster because you can login, then do all the transfers at once (it seems from a cursory glance that you execute ncftpput once for each file get/put).

Just remember to NEVER use ASCII mangling! This is the default, so use:
$ftp->binary


ASCII mangling needs to die in the same fire with MySQL automatic-timezone-interpreting.


Since I always end up having a problem with this, I'll post my notes here:

One thing I always get to confuse is the syntax; so below there is a bash tester script which creates some temporary directories, then starts a temporary ftp server, and compares rsync (in plain local file mode, as it doesn't support ftp) with lftp and ftpsync.

The thing is - you can use rsync /path/to/local /path/to/remote/, and rsync will automatically figure out, that you want a local subdirectory created under remote; however, for lftp or ftpsync you have to specify the target directory manually, as in ... /path/to/local /path/to/remote/local (if it doesn't exist it will be created).

You can find the ftpserver-cli.py in How do I temporarily run an FTP server? - Ask Ubuntu; and ftpsync is here: FTPsync (however, note it is buggy; see also Search/grep ftp remote filenames - Unix & Linux Stack Exchange);

Here is a shortened output of the puttest.sh script, showing the recursive put behavior in different cases:
$ bash puttest.sh
Recreate directories; populate loctest, keep srvtest empty:
show dirs:
+ tree --noreport -a /tmp/srvtest /tmp/loctest
/tmp/srvtest
/tmp/loctest
├── .git
│ └── tempa2.txt
└── tempa1.txt

*NOTE, rsync can automatically figure out parent dir:
+ rsync -a --exclude '*.git*' /tmp/loctest /tmp/srvtest/
show dirs:
+ tree --noreport -a /tmp/srvtest /tmp/loctest
/tmp/srvtest
└── loctest
└── tempa1.txt
/tmp/loctest
├── .git
│ └── tempa2.txt
└── tempa1.txt
cleanup:
+ rm -rf /tmp/srvtest/loctest

Start a temporary ftp server:
+ sudo bash -c 'python /path/to/pyftpdlib/ftpserver-cli.py --username=user --password=12345 --directory=/tmp/srvtest &'
+ sleep 1
Using: user: user pass: 12345 port: 21 dir: /tmp/srvtest
[I 14-03-02 23:24:01] >>> starting FTP server on 127.0.0.1:21, pid=21549 <<<
[I 14-03-02 23:24:01] poller: <class 'pyftpdlib.ioloop.Epoll'>
[I 14-03-02 23:24:01] masquerade (NAT) address: None
[I 14-03-02 23:24:01] passive ports: None
[I 14-03-02 23:24:01] use sendfile(2): False
test with lftp:

*NOTE, lftp syncs *contents* of local dir (rsync-like syntax doesn't create target dir):
+ lftp -e 'mirror -R -x ".*\.git.*" /tmp/loctest / ; exit' -u user,12345 127.0.0.1
show dirs:
+ tree --noreport -a /tmp/srvtest /tmp/loctest
/tmp/srvtest
└── tempa1.txt
/tmp/loctest
├── .git
│ └── tempa2.txt
└── tempa1.txt
cleanup:
+ rm -rf /tmp/srvtest/tempa1.txt

*NOTE, specify lftp target dir explicitly (will be autocreated):
+ lftp -e 'mirror -R -x ".*\.git.*" /tmp/loctest /loctest ; exit' -u user,12345 127.0.0.1
show dirs:
+ tree --noreport -a /tmp/srvtest /tmp/loctest
/tmp/srvtest
└── loctest
└── tempa1.txt
/tmp/loctest
├── .git
│ └── tempa2.txt
└── tempa1.txt
cleanup:
+ sudo rm -rf /tmp/srvtest/loctest

*NOTE, ftpsync syncs *contents* of local dir (rsync-like syntax doesn't create target dir); also info mode -i is buggy (it puts, although it shouldn't):

*NOTE, ftpsync --ignoremask is for older unused code; use --exclude instead (but it is buggy; need to change in source)
+ /path/to/ftpsync/ftpsync -i -d '--exclude=.*\.git.*' /tmp/loctest ftp://user:[email protected]/
show dirs:
+ tree --noreport -a /tmp/srvtest /tmp/loctest
/tmp/srvtest
└── tempa1.txt
/tmp/loctest
├── .git
│ └── tempa2.txt
└── tempa1.txt
cleanup:
+ sudo rm -rf /tmp/srvtest/tempa1.txt

*NOTE, specify ftpsync target dir explicitly (will be autocreated):
+ /path/to/ftpsync/ftpsync -i -d '--exclude=.*\.git.*' /tmp/loctest ftp://user:[email protected]/loctest
show dirs:
+ tree --noreport -a /tmp/srvtest /tmp/loctest
/tmp/srvtest
└── loctest
└── tempa1.txt
/tmp/loctest
├── .git
│ └── tempa2.txt
└── tempa1.txt
cleanup:
+ sudo rm -rf /tmp/srvtest/loctest
+ sudo pkill -f ftpserver-cli.py


And, here is the puttest.sh script:
#!/usr/bin/env bash
set -x

# change these to match your installations:
FTPSRVCLIPATH="/path/to/pyftpdlib"
FTPSYNCPATH="/path/to/ftpsync"

{ echo "Recreate directories; populate loctest, keep srvtest empty:"; } 2>/dev/null

sudo rm -rf /tmp/srvtest /tmp/loctest

mkdir /tmp/srvtest

mkdir -p /tmp/loctest/.git
echo aaa > /tmp/loctest/tempa1.txt
echo aaa > /tmp/loctest/.git/tempa2.txt

{ echo "show dirs:"; } 2>/dev/null
tree --noreport -a /tmp/srvtest /tmp/loctest

{ echo -e "\n*NOTE, rsync can automatically figure out parent dir:"; } 2>/dev/null

rsync -a --exclude '*.git*' /tmp/loctest /tmp/srvtest/

{ echo "show dirs:"; } 2>/dev/null
tree --noreport -a /tmp/srvtest /tmp/loctest

{ echo "cleanup:"; } 2>/dev/null
rm -rf /tmp/srvtest/*

{ echo -e "\nStart a temporary ftp server:"; } 2>/dev/null

# http://askubuntu.com/questions/17084/how-do-i-temporarily-run-an-ftp-server

sudo bash -c "python $FTPSRVCLIPATH/ftpserver-cli.py --username=user --password=12345 --directory=/tmp/srvtest &"
sleep 1

{ echo "test with lftp:"; } 2>/dev/null
# see http://russbrooks.com/2010/11/19/lftp-cheetsheet
# The -R switch means "reverse mirror" which means "put" [upload].
{ echo -e "\n*NOTE, lftp syncs *contents* of local dir (rsync-like syntax doesn't create target dir):"; } 2>/dev/null

lftp -e 'mirror -R -x ".*\.git.*" /tmp/loctest / ; exit' -u user,12345 127.0.0.1

{ echo "show dirs:"; } 2>/dev/null
tree --noreport -a /tmp/srvtest /tmp/loctest

{ echo "cleanup:"; } 2>/dev/null
rm -rf /tmp/srvtest/*

{ echo -e "\n*NOTE, specify lftp target dir explicitly (will be autocreated):"; } 2>/dev/null

lftp -e 'mirror -R -x ".*\.git.*" /tmp/loctest /loctest ; exit' -u user,12345 127.0.0.1

{ echo "show dirs:"; } 2>/dev/null
tree --noreport -a /tmp/srvtest /tmp/loctest

{ echo "cleanup:"; } 2>/dev/null
sudo rm -rf /tmp/srvtest/*

{ echo -e "\n*NOTE, ftpsync syncs *contents* of local dir (rsync-like syntax doesn't create target dir); also info mode -i is buggy (it puts, although it shouldn't):"; } 2>/dev/null
{ echo -e "\n*NOTE, ftpsync --ignoremask is for older unused code; use --exclude instead (but it is buggy; need to change ` 'exclude=s' => \$opt::exclude,` in source)"; } 2>/dev/null

$FTPSYNCPATH/ftpsync -i -d --exclude='.*\.git.*' /tmp/loctest ftp://user:[email protected]/

{ echo "show dirs:"; } 2>/dev/null
tree --noreport -a /tmp/srvtest /tmp/loctest

{ echo "cleanup:"; } 2>/dev/null
sudo rm -rf /tmp/srvtest/*

{ echo -e "\n*NOTE, specify ftpsync target dir explicitly (will be autocreated):"; } 2>/dev/null

$FTPSYNCPATH/ftpsync -i -d --exclude='.*\.git.*' /tmp/loctest ftp://user:[email protected]/loctest

{ echo "show dirs:"; } 2>/dev/null
tree --noreport -a /tmp/srvtest /tmp/loctest

{ echo "cleanup:"; } 2>/dev/null
sudo rm -rf /tmp/srvtest/*


sudo pkill -f ftpserver-cli.py

{ set +x; } 2>/dev/null

 


Top Visited
Switchboard
Latest
Past week
Past month

NEWS CONTENTS

Old News ;-)

[Mar 22, 2015] Linux - Unix ncftp Upload Directory Tree To Remote FTP Server Recursively

April 27, 2005 | nixCraft

by nixCraft on April 27, 2005 · 8 comments· LAST UPDATED October 28, 2012

When you host your web site remotely and and the ftp server is the only way to upload all files including subdirectroies. You need to use special file transfer program such as ncftpget or ncftpput for recursive remote ftp server uploading and downloading purpose. Ncftp is considered as an improved FTP client. Ncftp's improvements include support for command line editing, command histories, recursive gets/puts, automatic anonymous logins, and much more.

... ... ...

The syntax is as follows:

 
ncftpput ftp-host-name /path/to/remote/dir /path/to/local/dir
ncftpput -options ftp-host-name /path/to/remote/dir /path/to/local/dir
 

Try the ncftpput client command as follows:

 
ncftpput -R -v -u "username" ftp.nixcraft.biz /nixcraft/forum /tmp/phpbb
 

Where,

You can pass the password with -p option:

 
ncftpput -R -v -u "username" -p "passwordHere" ftp.nixcraft.biz /nixcraft/forum /tmp/phpbb
 

You can use port number 2021 instead of the default FTP service port # 21 as follows:

 
ncftpput -R -v -u "username" -p "passwordHere" -P 2021 ftp.nixcraft.biz /nixcraft/forum /tmp/phpbb
 
See also

recursion - Recursively PUT files to a remote server using FTP

Sep 10, 2010 | Stack Overflow

I'm currently in a situation where I have very limited access to a server, but need to upload and download a significant amount of files contained within a single directory structure. I don't have SSH access, so I can't use SCP - and rsync isn't an option either unfortunately.

I'm currently using ncftpput, which is great but seems to be quite slow (in spite of a fast connection).

Is there an alternative / better method I could look into?

(Please accept my apologies if this has been covered, I did a quick search prior to posting but didn't find anything that specifically answered my question)

Answers

Try using LFTP: http://lftp.yar.ru/

or YAFC: http://yafc.sourceforge.net/index.php


2

for ncftp - are you using "put -R" command to do a recursive directory upload? – DmitryK Sep 10 '09 at 2:38

I am indeed - I think part of the problem is FTP is quite antiquated.. so there might not be an ideal solution – codeinthehole Sep 10 '09 at 3:29

If you have a good connection, I would recommend mounting the ftp server via the GNOME or KDE file managers, or else using CurlFtpFS. Then you can treat it like just another folder.


This is a horrible answer. There is no way that doing this would be faster than FTP, and it's a lot more risky, especially with high volumes of data, as it doesn't support resume on interrupt. And if he doesn't have access to SSH, how is he going to configure it for mounting? – Benubird Mar 15 '13 at 11:49


No server configuration is required. The server is already configured for FTP. And the point isn't to make things faster, it's to make them easier. After mounting with CurlFtpFS, once could use standard unix utils like cp and rsync. I did say it works best with a good connection. – Ryan Thompson Mar 15 '13 at 15:27

I'm not familiar with ncftpput. For non-interactive FTP, I've always used the Perl Net::FTP module -- http://perldoc.perl.org/Net/FTP.html

This will be faster because you can login, then do all the transfers at once (it seems from a cursory glance that you execute ncftpput once for each file get/put).

Just remember to NEVER use ASCII mangling! This is the default, so use:
$ftp->binary


ASCII mangling needs to die in the same fire with MySQL automatic-timezone-interpreting.


Since I always end up having a problem with this, I'll post my notes here:

One thing I always get to confuse is the syntax; so below there is a bash tester script which creates some temporary directories, then starts a temporary ftp server, and compares rsync (in plain local file mode, as it doesn't support ftp) with lftp and ftpsync.

The thing is - you can use rsync /path/to/local /path/to/remote/, and rsync will automatically figure out, that you want a local subdirectory created under remote; however, for lftp or ftpsync you have to specify the target directory manually, as in ... /path/to/local /path/to/remote/local (if it doesn't exist it will be created).

You can find the ftpserver-cli.py in How do I temporarily run an FTP server? - Ask Ubuntu; and ftpsync is here: FTPsync (however, note it is buggy; see also Search/grep ftp remote filenames - Unix & Linux Stack Exchange);

Here is a shortened output of the puttest.sh script, showing the recursive put behavior in different cases:
$ bash puttest.sh
Recreate directories; populate loctest, keep srvtest empty:
show dirs:
+ tree --noreport -a /tmp/srvtest /tmp/loctest
/tmp/srvtest
/tmp/loctest
├── .git
│ └── tempa2.txt
└── tempa1.txt

*NOTE, rsync can automatically figure out parent dir:
+ rsync -a --exclude '*.git*' /tmp/loctest /tmp/srvtest/
show dirs:
+ tree --noreport -a /tmp/srvtest /tmp/loctest
/tmp/srvtest
└── loctest
└── tempa1.txt
/tmp/loctest
├── .git
│ └── tempa2.txt
└── tempa1.txt
cleanup:
+ rm -rf /tmp/srvtest/loctest

Start a temporary ftp server:
+ sudo bash -c 'python /path/to/pyftpdlib/ftpserver-cli.py --username=user --password=12345 --directory=/tmp/srvtest &'
+ sleep 1
Using: user: user pass: 12345 port: 21 dir: /tmp/srvtest
[I 14-03-02 23:24:01] >>> starting FTP server on 127.0.0.1:21, pid=21549 <<<
[I 14-03-02 23:24:01] poller: <class 'pyftpdlib.ioloop.Epoll'>
[I 14-03-02 23:24:01] masquerade (NAT) address: None
[I 14-03-02 23:24:01] passive ports: None
[I 14-03-02 23:24:01] use sendfile(2): False
test with lftp:

*NOTE, lftp syncs *contents* of local dir (rsync-like syntax doesn't create target dir):
+ lftp -e 'mirror -R -x ".*\.git.*" /tmp/loctest / ; exit' -u user,12345 127.0.0.1
show dirs:
+ tree --noreport -a /tmp/srvtest /tmp/loctest
/tmp/srvtest
└── tempa1.txt
/tmp/loctest
├── .git
│ └── tempa2.txt
└── tempa1.txt
cleanup:
+ rm -rf /tmp/srvtest/tempa1.txt

*NOTE, specify lftp target dir explicitly (will be autocreated):
+ lftp -e 'mirror -R -x ".*\.git.*" /tmp/loctest /loctest ; exit' -u user,12345 127.0.0.1
show dirs:
+ tree --noreport -a /tmp/srvtest /tmp/loctest
/tmp/srvtest
└── loctest
└── tempa1.txt
/tmp/loctest
├── .git
│ └── tempa2.txt
└── tempa1.txt
cleanup:
+ sudo rm -rf /tmp/srvtest/loctest

*NOTE, ftpsync syncs *contents* of local dir (rsync-like syntax doesn't create target dir); also info mode -i is buggy (it puts, although it shouldn't):

*NOTE, ftpsync --ignoremask is for older unused code; use --exclude instead (but it is buggy; need to change in source)
+ /path/to/ftpsync/ftpsync -i -d '--exclude=.*\.git.*' /tmp/loctest ftp://user:[email protected]/
show dirs:
+ tree --noreport -a /tmp/srvtest /tmp/loctest
/tmp/srvtest
└── tempa1.txt
/tmp/loctest
├── .git
│ └── tempa2.txt
└── tempa1.txt
cleanup:
+ sudo rm -rf /tmp/srvtest/tempa1.txt

*NOTE, specify ftpsync target dir explicitly (will be autocreated):
+ /path/to/ftpsync/ftpsync -i -d '--exclude=.*\.git.*' /tmp/loctest ftp://user:[email protected]/loctest
show dirs:
+ tree --noreport -a /tmp/srvtest /tmp/loctest
/tmp/srvtest
└── loctest
└── tempa1.txt
/tmp/loctest
├── .git
│ └── tempa2.txt
└── tempa1.txt
cleanup:
+ sudo rm -rf /tmp/srvtest/loctest
+ sudo pkill -f ftpserver-cli.py


And, here is the puttest.sh script:
#!/usr/bin/env bash
set -x

# change these to match your installations:
FTPSRVCLIPATH="/path/to/pyftpdlib"
FTPSYNCPATH="/path/to/ftpsync"

{ echo "Recreate directories; populate loctest, keep srvtest empty:"; } 2>/dev/null

sudo rm -rf /tmp/srvtest /tmp/loctest

mkdir /tmp/srvtest

mkdir -p /tmp/loctest/.git
echo aaa > /tmp/loctest/tempa1.txt
echo aaa > /tmp/loctest/.git/tempa2.txt

{ echo "show dirs:"; } 2>/dev/null
tree --noreport -a /tmp/srvtest /tmp/loctest

{ echo -e "\n*NOTE, rsync can automatically figure out parent dir:"; } 2>/dev/null

rsync -a --exclude '*.git*' /tmp/loctest /tmp/srvtest/

{ echo "show dirs:"; } 2>/dev/null
tree --noreport -a /tmp/srvtest /tmp/loctest

{ echo "cleanup:"; } 2>/dev/null
rm -rf /tmp/srvtest/*

{ echo -e "\nStart a temporary ftp server:"; } 2>/dev/null

# http://askubuntu.com/questions/17084/how-do-i-temporarily-run-an-ftp-server

sudo bash -c "python $FTPSRVCLIPATH/ftpserver-cli.py --username=user --password=12345 --directory=/tmp/srvtest &"
sleep 1

{ echo "test with lftp:"; } 2>/dev/null
# see http://russbrooks.com/2010/11/19/lftp-cheetsheet
# The -R switch means "reverse mirror" which means "put" [upload].
{ echo -e "\n*NOTE, lftp syncs *contents* of local dir (rsync-like syntax doesn't create target dir):"; } 2>/dev/null

lftp -e 'mirror -R -x ".*\.git.*" /tmp/loctest / ; exit' -u user,12345 127.0.0.1

{ echo "show dirs:"; } 2>/dev/null
tree --noreport -a /tmp/srvtest /tmp/loctest

{ echo "cleanup:"; } 2>/dev/null
rm -rf /tmp/srvtest/*

{ echo -e "\n*NOTE, specify lftp target dir explicitly (will be autocreated):"; } 2>/dev/null

lftp -e 'mirror -R -x ".*\.git.*" /tmp/loctest /loctest ; exit' -u user,12345 127.0.0.1

{ echo "show dirs:"; } 2>/dev/null
tree --noreport -a /tmp/srvtest /tmp/loctest

{ echo "cleanup:"; } 2>/dev/null
sudo rm -rf /tmp/srvtest/*

{ echo -e "\n*NOTE, ftpsync syncs *contents* of local dir (rsync-like syntax doesn't create target dir); also info mode -i is buggy (it puts, although it shouldn't):"; } 2>/dev/null
{ echo -e "\n*NOTE, ftpsync --ignoremask is for older unused code; use --exclude instead (but it is buggy; need to change ` 'exclude=s' => \$opt::exclude,` in source)"; } 2>/dev/null

$FTPSYNCPATH/ftpsync -i -d --exclude='.*\.git.*' /tmp/loctest ftp://user:[email protected]/

{ echo "show dirs:"; } 2>/dev/null
tree --noreport -a /tmp/srvtest /tmp/loctest

{ echo "cleanup:"; } 2>/dev/null
sudo rm -rf /tmp/srvtest/*

{ echo -e "\n*NOTE, specify ftpsync target dir explicitly (will be autocreated):"; } 2>/dev/null

$FTPSYNCPATH/ftpsync -i -d --exclude='.*\.git.*' /tmp/loctest ftp://user:[email protected]/loctest

{ echo "show dirs:"; } 2>/dev/null
tree --noreport -a /tmp/srvtest /tmp/loctest

{ echo "cleanup:"; } 2>/dev/null
sudo rm -rf /tmp/srvtest/*


sudo pkill -f ftpserver-cli.py

{ set +x; } 2>/dev/null



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-2021 by Softpanorama Society. www.softpanorama.org was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) 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 to buy a cup of coffee for authors of this site

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 Softpanorama society. 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: March, 12, 2019