Re: Call for input on comp.unix.shell FAQ
From: Heiner Steven (heiner.steven_at_nexgo.de)
Date: 07/15/03
- Next message: Scott Coffland: "grep search on command history file does not work on Tru64 Unix"
- Previous message: Chris F.A. Johnson: "Re: kshell: var. within a var."
- In reply to: Joe Halpin: "Re: Call for input on comp.unix.shell FAQ"
- Next in thread: Stephane CHAZELAS: "Re: Call for input on comp.unix.shell FAQ"
- Reply: Stephane CHAZELAS: "Re: Call for input on comp.unix.shell FAQ"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Date: Tue, 15 Jul 2003 23:13:58 +0200
Joe Halpin wrote:
> Stephane CHAZELAS <stephane_chazelas@yahoo.fr> writes:
>
>>Faux_Pseudo wrote:
>>[...]
>>
>>>I think that a FAQ for this group would be great and I would love to
>>>help put it together so that we can stop answering the same old
>>>questions and just tell people to FAQ it.
>>
>>[...]
>>
>>Agreed. So, Joe, did you start something? You could post your
>>first draft to this group once you've got something, so that we
>>can comment or complete it.
>
>
> This isn't exactly a first draft. However, I'm pretty busy now, and
> things are going more slowly than I anticipated. So here's what I have
> to this point. If anyone wants to contribute an answer that isn't
> there yet, I'll be happy to take it :-)
>
> Also, please let me know if you see anything that isn't correct.
>
> Archive-name: comp-unix-shell-faq/faq/cus-faq
> Version: $Id$
> Maintained By: Joe Halpin <j.p.h@comcast.net>
>
> This FAQ contains the answers to some Frequently Asked Questions
> often seen in comp.unix.shell. It spells "unix" in lower case letters
> to avoid arguments about whether or not Linux, FreeBSD, etc are
> unix. That's not the point of this FAQ, and I'm ignoring the issue.
>
> There are two levels of questions about shells.
>
> One is the use of the shell itself as an interface to the operating
> system. For example, "how do I run a program in the background, and go
> on with other things?". Or "how do I setup environmental variables
> when I log in?".
>
> The other level is how to write shell scripts. This often involves
> having the shell execute unix utilities to perform part of the work
> the shell script needs to accomplish, and requires knowledge of these
> utilities, which isn't nominally in the scope of shell
> programming. However, unless the question involves something other
> than standard unix utilities, it should be included in this FAQ.
>
> Standard unix utilities are defined by either POSIX or the Single Unix
> Specification. These are now joined and are normally abbreviated as
> "POSIX/SUS". This specification can be found at
>
> http://www.opengroup.org/onlinepubs/007904975/toc.htm
>
> The man pages found on that web page define standard behavior for any
> given utility (or the shell itself). However, you should also check
> the man page on your system for any utility or shell you need to
> use. There isn't always a perfect correspondence between the standard
> and a particular implementation (in fact, I'm not sure there's any
> case in which they perfectly correspond).
>
> Other good web sites that provide information about shells and shell
> programming (including OS utilities) include:
>
> http://www.shelldorado.com/
> http://www.faqs.org/faqs/by-newsgroup/comp/comp.unix.shell.html
>
> The answers given in this FAQ are provided with the best intentions,
> but they may not be accurate for any particular shell/os. They may be
> completely wrong. If you don't test the answers, that's a bug in your
> procedures. There are no guarantees for the answers given here.
>
> If you do test the answers and find a problem, please send email to
> the maintainer, so it can be corrected. However, under no
> circumstances will the maintainer be held liable for mistakes in this
> FAQ. If the answers work for you, well and good. If not, please tell
> me and I'll modify them appropriately so that this will be more
> useful. If you don't agree with this, stop reading here.
>
> A number of people have contributed to this FAQ, knowingly or
> unknowingly. Some of the answers were taken from previous postings in
> the group, and other people contributed questions and answers
> directly to the maintainer, which you are welcome to do as well.
>
> (For the group -- Please let me know if you'd like your name and/or
> email address listed here when you contribute something)
>
> CONTENTS:
>
> 0. Glossary
> 1. How can I send e-mails with attached files?
> 2. How can I generate random numbers in shell scripts?
> 3. How can I automatically transfer files using FTP with error checking?
> 4. How can I remove whitespace characters within file names?
> 5. How can I automate a telnet session?
> 6. How do I get yesterdays date?
> 7. Why did someone tell me to RTFM?
> 8. Why is csh harmful to my health?
> 9. How do I create a lock file?
> 10. How to get a date with x <time unit> of difference?
> 11. What is way to remane files w/ odd charcaters in their name?
> 12. How can (CRLF|LF|LFCR) be translated into one of the other?
> 13. How a shell prompt can be set up to change the title of xterm?
> 14. How to batch a FTP download/upload?
> 15. How to get the exit code of cmd1 in cmd1|cmd2
> 16. "script.sh: no found" while script starts with "#!/bin/sh" (^M issue)
> 17. Why one shouldn't use "echo" in a script?
> 18. how to loop through files with spaces in their name?
> 19. how to change my login shell to zsh?
> 20. when to use shells instead of perl/python/ruby/tcl...
> 21. why shouldn't I use csh?
> 22. why is shell programming considered harmful?
> 23. what shell should I use for scripting?
> 24. how to reverse a file?
> 25. how to remove last 10 lines?
> 26. how to get a file size, a file modification time?
> 27. how to get a process id by process argv[0]?
> 28. how to get a script to update my current environment?
> 29. how to find files less than 15 minute old?
> 30. how can I know wether my script is portable?
> 31. how do I rename *.foo to *.bar?
> 32. how to redirect stdout to file1 stderr to file2 while still
> seeing them on screen?
> 33. how to loop through *.txt files and treat the case when
> there's no such file (+ dotfile issue).
> 34. why isn't var set in "cmd | read var"
> 35. how to use shell variables in awk scripts
> 36. date manipulations
> 37. how to input the user with a timeout?
> 38. how to input user for only one char?
> 39. why isn't my .profile read?
> 40. known incompatibilities/limitations in sed/grep/awk/...
> 41. why do I get "[5" not found in "[$1 -eq 2]"?
> 42. how to deal with dot files?
> 43 why is zsh the best shell? ;)
> 44. How to exactly display the content of $var (with a \n appended).
> 45. How to exactly display the content of $var (without a \n
> appended).
>
>
> ANSWERS
>
> 0. Glossary
>
> a. shebang
>
> This is the first line of a shell script, which indicates to the
> operating system which interpreter (shell) it should invoke to
> interpret the script. It has the form
>
> #!/path/to/shell [ argument ]
>
> where /path/to/shell might be /bin/sh, /usr/local/bin/bash, etc.
>
> This line is only interpreted by the operating system. That is,
> if a shell script (test.sh) is executable and run from the
> command line by typing its name.
>
> If it's run by typing
>
> $ sh test.sh
>
> then sh is run with the argument "test.sh". It then interprets
> test.sh. For sh, the shebang line is simply a comment, and is
> ignored.
>
> b. race condition
>
> This is a situation in which two entities (processes, threads,
> etc) are trying to access a shared resource, or perform the same
> action, and the result depends on the order of execution of the
> two entities.
>
> 1. How can I send e-mails with attached files?
>
> a. Use uuencode
>
> This is the simplest way to do this. For example
>
> $ uuencode surfing.jpeg surfing.jpeg | mail sylvia@home.com
>
> To send regular text as well
>
> $ (cat mailtext; uuencode surfing.jpeg surfing.jpeg) |
> mail sylvia@home.com
>
> b. Use MIME
>
> $ metasend -b -t john@friends.org -s "Hear our son!" \
> -m audio/basic -f crying.au
>
> These examples are taken from
> http://www.shelldorado.com/articles/mailattachments.html which
> goes into much more detail about this.
>
> 2. How can I generate random numbers in shell scripts?
>
> This depends on the shell, and the facilities available from the
> OS.
>
> a. Some shells have a variable called RANDOM, which evaluates to a
> different value every time you dereference it. If your shell has
> this variable,
>
> $ number=$RANDOM will produce a random number.
>
> b. Some systems have a /dev/urandom device, which generates a
> stream of bits. This can be accessed using the dd(1) utility. An
> example of this (from a more extensive discussion of different
> techniques at http://www.shelldorado.com/scripts/cmds/rand)
>
> n=`dd if=/dev/urandom bs=1 count=4 2>/dev/null | od -t u4 | \
> awk 'NR==1 {print $2}'`
>
> c. Use a utility such as awk(1), which has random number generation
> included. This approach is the most portable between shells.
>
> awk -v seed="$$" 'BEGIN {srand(seed);print rand()}'
As Stephane already pointed out, omitting the "seed" parameter
yields better (more random) results, because the default parameter
is the time.
> However, note that if you call this line more than once without
> changing the seed, you'll get the same number you did the
> previous time.
>
> 3. How can I automatically transfer files using FTP with error
> checking?
>
> First, there are tools to do that: curl, wget, lftp, ncftp. But, they
> are generally not part of the base system (you need to install them).
>
> zsh (version 4 and above) provides a FTP facility, see
> "info -f zsh -n 'zsh/zftp Module'"
>
> #! /usr/bin/zsh
> zftp open host user passwd || exit
> zftp get /remote/file > /local/file; r=$?
> zftp close && exit r
>
> With your system "ftp" command, two ways:
>
> 1- using "ftp -n". Without the -n option, ftp expects user interaction
> to enter the password, so you'd need to use "expect". With "-n", you
> provide the user and passwd as any other FTP command.
>
> #! /bin/sh
> ftp -n << EOF
> open ftp.domain.org
> user anonymous ${LOGNAME:-`who am i`}@
> binary
> get /remote/file /local/file
> bye
> EOF
>
> The error checking can't be made correctly (if "open" fails, the "user"
> command will be still sent even if it shouldn't).
>
> 2- using ~/.netrc
>
> If you put:
>
> <<
> machine ftp.domain.org
> login mylogin
> password mypasswd
> macdef init
> binary
> get /remote/file /local/file
> bye
>
>
> >>
>
> (with the trailing empty line) in your ~/.netrc (ensure it's not world
> readable) and then run "ftp ftp.domain.org", ftp will find the matching
> "machine" entry in your ~/.netrc and use the parameters provided there
> to make the ftp transaction.
>
> Those work at least on Linux, FreeBSD, Solaris, HPUX
>
> 4. How can I remove whitespace characters within file names?
>
> a. Use the substitution capabilites of awk, sed, et al.
>
> f=`echo "$filename" | sed 's/ /_/g'` #replace with '_'
Why not use the command that was created particularly for
the purpose of replacing one character with another?
f=`echo "$filename" | tr ' ' _`
> f=`echo "$filename" | awk '{gsub(" ","_");print $0}'`
>
> b. Use the substitution capabilities of the shell if it has
> them. Check the man page for your shell (probably under a
> section named something like "Parameter expansion") to see. The
> following works with bash
...and ksh93:
> f=${filename// /_}
>
> 5. How can I automate a telnet session?
>
> This is outside the realm of shell programing, per se. You need
> a more special purpose scripting language such as expect. See
> http://expect.nist.gov/
>
> Perl scripts can also do this with the Telnet module from CPAN.
There is a crude way of using the "telnet" command that uses
"sleep" to wait until the command started up and established
a connection:
user=joe
passwd=secret
host=remhost
cmd="ls -l"
(
sleep 2 # give "telnet" time to start up and connect
echo "$user"; sleep 2
echo "$passwd"; sleep 2
echo "$cmd" # run command!
sleep 2 # give time to print results
) | telnet "$host"
> 6. How do I get yesterdays date?
>
> (There are a number of responses to this on Google Groups. However
> there are so many options that I'm not sure how to approach
> this. I'm not sure duplicating the threads on Google is appropriate
> for a FAQ. Suggestions would be appreciated.)
>
> 7. Why did someone tell me to RTFM?
>
> Because you didn't :-)
>
> RTFM is part of Usenet lingo, and means "Read The F-ing Manual".
> Generally people say this when someone asks a question that is
> asked so often, and is answered plainly in some relevant man page,
> that they're tired of seeing it asked.
>
> So RTFM, and the FAQs first before asking. Also, if you're new to
> the group, search Google Groups
>
> http://groups.google.com/advanced_group_search
>
> before asking questions. And please don't post your homework
> questions to the group unless you've tried to figure them out, and
> have some specific questions. People will be generally be happy to
> help you with your homework if you post what you've got and ask
> specific questions.
>
> 8. Why is csh harmful to my health?
>
> 9. How do I create a lock file?
>
> Very carefully :-)
>
> The scheduler can stop one process in the middle of a non-atomic
> operation, and run another one, which wants to perform the same
> operation. The second one, having a full timeslice, might finish
> the operation. When control returns to the first process, confusion
> will reign.
>
> The trick is to do something atomic, so that this won't
> happen. There are a couple ways to do this. One is to create a
> directory instead of a file, the other is to create a symbolic
> link. Both operations are defined to be atomic by POSIX/SUS, by
> virtue of the fact that they both require calls to the
> corresponding system calls, which are atomic. Even here though,
> there is a window of opportunity for bad things to happen. There is
> some startup code in the command line version of mkdir(1) and
> ln(1), which could get interrupted before the system call is
> invoked. However, this is as close as we can get to perfection in a
> shell script.
>
> For the same reason, beware of testing for the existence of the
> lock file before trying to create it. That will just increase the
> window of possibility for a race condition.
>
> Be even more afraid of trying to create ANY kind of lock file on an
> NFS partition. NFS pretty much eliminates anything like
> atomicity. If you're going to create a lock file, make sure you're
> doing it on a local partition, such as /tmp.
>
> Netscape/Mozilla uses the symbolic link method for its lockfile (in
> spite of the fact that it creates it in the user's home directory,
> which may be NFS mounted). When it starts up it creates a file
> named for the IP address of the machine it's running on, and the
> pid of the creating process. Then it tries to create a symbolic
> link named "lock", which points to that file. If this symlink
> already exists, link(2) will return an error. In a script this
> would work something like
>
> touch /tmp/$$
> ln -s /tmp/$$ /tmp/lockfile 2>/dev/null
> if [ $? -ne 0 ];then
> echo lockfile already exists
> rm /tmp/$$
> exit 1
> else
> echo success
> rm /tmp/$$
> fi
>
> If you have procmail installed, another possiblity is the
> lockfile(1) command that comes with it. Many of the same caveats
> given above apply to that as well though.
>
> 10. How to get a date with x <time unit> of difference?
>
> 11. What is way to remane files w/ odd charcaters in their name?
>
> 12. How can (CRLF|LF|LFCR) be translated into one of the other?
Unix text files consist of lines delimited by an LF
("line-feed") character (ASCII 10). DOS uses the two
characters CR LF ("carriage return", "line feed";
ASCII 13, 10) for the same purpose.
To convert a DOS text into unix text format, the
CR characters (control-M) at the end of a line have to
be removed:
sed 's/^M$//' dos.txt > unix.txt
To create a DOS text file, the CR character should be added:
sed 's/$/^M/' unix.txt > dos.txt
Note that "^M" in this case is an embedded control character,
(CR, ASCII 13). Many shells allow embedding control characters
by entering ^V first (control-V), resulting in the sequence
^V^M
for entering "^M".
There is one special case to be considered: DOS text files
sometimes contain an explicit end-of-file character
^Z (ASCII 26), which has no correspondent character for
unix text files, where the end-of-file condition is determined
implicitly.
[XXX Does anybody have an easy solution to handle this?
sed '$s/^Z$//' may not work, because some sed implementations
cannot handle lines that are not terminated by LF]
> 13. How a shell prompt can be set up to change the title of xterm?
> 14. How to batch a FTP download/upload?
> 15. How to get the exit code of cmd1 in cmd1|cmd2
>
> First, note that cmd1 exit code could be non-zero and still don't
> mean an error. This happens for instance in
>
> cmd | head -1
>
> you might observe a 141 (or 269 with ksh93) exit status of cmd1,
> but it's because cmd was interrupted by a SIGPIPE signal when
> "head -1" terminated after having read one line.
>
> To know the exit status of the elements of a pipeline
> cmd1 | cmd2 | cmd3
>
> a. with zsh:
>
> The exit codes are provided in the pipestatus special array.
> cmd1 exit code is in $pipestatus[1], cmd3 exit code in
> $pipestatus[3], so that $? is always the same as
> $pipestatus[-1].
>
> b. with bash:
>
> The exit codes are provided in the PIPESTATUS special array.
> cmd1 exit code is in ${PIPESTATUS[0]}, cmd3 exit code in
> ${PIPESTATUS[2]}, so that $? is always the same as
> ${PIPESTATUS: -1}.
>
> c. with any other Bourne like shells
>
> You need to use a trick to pass the exit codes to the main
> shell. You can do it using a pipe(2). Instead of running
> "cmd1", you run "cmd1; echo $?" and make sure $? makes it way
> to the shell.
>
> exec 3>&1
> eval `
> # now, inside the `...`, fd4 goes to the pipe
> # whose other end is read and passed to eval;
> # fd1 is the normal standard output preserved
> # the line before with exec 3>&1
> exec 4>&1 >&3 3>&-
> {
> cmd1 4>&-; echo "ec1=$?;" >&4
> } | {
> cmd2 4>&-; echo "ec2=$?;" >&4
> } | cmd3
> echo "ec3=$?;" >&4
> `
>
> d. with a POSIX shell
>
> You can use this function to make it easier:
>
> run() {
> j=1
> while eval "\${pipestatus_$j+:} false"; do
> unset pipestatus_$j
> j=$(($j+1))
> done
> j=1 com= k=1 l=
> for a; do
> if [ "x$a" = 'x|' ]; then
> com="$com { $l "'3>&-
> echo "pipestatus_'$j'=$?" >&3
> } 4>&- |'
> j=$(($j+1)) l=
> else
> l="$l \"\$$k\""
> fi
> k=$(($k+1))
> done
> com="$com $l"' 3>&- >&4 4>&-
> echo "pipestatus_'$j'=$?"'
> exec 4>&1
> eval "$(exec 3>&1; eval "$com")"
> exec 4>&-
> j=1
> while eval "\${pipestatus_$j+:} false"; do
> eval "[ \$pipestatus_$j -eq 0 ]" || return 1
> j=$(($j+1))
> done
> return 0
> }
>
> use it as:
>
> run cmd1 \| cmd2 \| cmd3
> exit codes are in $pipestatus_1, $pipestatus_2, $pipestatus_3
>
> 16. "script.sh: not found"
>
> a. While script starts with "#!/bin/sh" (^M issue)
>
> That's the kind of error that occurs when you transfer a file
> by FTP from a MS Windows machine. On those systems, the line
> separator is the CRLF sequence, while on unix the line
> separator is LF alone, CR being just another ordinary character
> (the problem is that it is an invisible one on your terminal
> (where it actually moves the cursor to the beginning of the
> line) or in most text editors or pagers).
>
> So, if a MSDOS line is "#!/bin/sh", when on a Unix system, it
> becomes "#!/bin/sh<CR>" (other names for <CR> are \r, \015, ^M,
> <Ctrl-M>).
>
> So, if you run the file as a script, the system will look in
> /bin for an interpreter named "sh<CR>", and report it doesn't
> exist.
>
> $ sed 'l;d;q' < script.sh
> #!/bin/sh\r$
>
> shows you the problem ($ marks the end of line, \r is the CR
> character).
>
> b. PATH issue
>
> Sometimes a shell is installed someplace other than /bin or
> /usr/bin. For example, a shell which was not part of the OS
> installation might be installed into /usr/local/bin. If the
> script was written on a machine which had ksh located in
> /usr/bin, but was run on a machine where ksh was located in
> /usr/local/bin, the shebang line would not resolve correctly.
>
> This is unlikely to occur when using sh. However, if the shell
> is bash, zsh, et al, it might be installed in different places
> on different machines.
>
> One way around this is to use the env command in the shebang
> line. So instead of
>
> #!/bin/sh
>
> use
>
> #!/usr/bin/env sh
>
> Of course, env might itself live in some other directory than
> /usr/bin, but it's not likely.
>
> 17. Why one shouldn't use "echo" in a script?
[XXX Why shouldn't one?
Maybe the question should be rephrased as
Why using "echo" in a script may not yield the expected results
]
> 18. how to loop through files with spaces in their name?
>
> So, you're going to loop through a list of files? How is this list
> stored? If it's stored as text, there probably was already an
> assumption about the characters allowed in a filename. Every
> character except '\0' (NUL)
...and '/' are...
> allowed in a file name on Unix
('/' is used as a delimiter for directory names).
If file names with embedded white space are specified on
the command line, or are generated by a file name pattern
(e.g. "for file in *; do ..."), white space can be preserved
by careful quoting, e.g.
for file in *
do
case "$file" in
*" "*) echo >&2 "name has embedded spaces: $file";;
esac
done
KornShell scripts can also use arrays that correctly preserve
embedded whitespace:
set -A dirtable -- "two
lines" "a b" "c d"
for dir in "${dirtable[@]}"
do
echo "dir=<$dir>"
done
When a list of file names is to be stored and read from
a file, keeping embedded whitespace characters becomes
more difficult.
> [So]
> The only way to store a list of file names in a file is to
> separate them by a '\0' character (if you don't use a quoting
> mechanism as for xargs input).
>
> Unfortunately most shells (except zsh) and most standard unix text
> utilities (except GNU ones) can't cope with "\0"
> characters. Moreover, many tools, like "ls", "find", "grep -l"
> output a \n separated list of files. So, if you want to
> postprocess this output, the simpler is to assume that the
> filenames don't contain newline characters (but beware that once
> you make that assumption, you can't pretend anymore your code is
> reliable (and thus can't be exploited)).
>
> So, if you've got a newline separated list of files in a
> list.txt file, Here are two ways to process it:
>
> 1-
>
> while IFS= read -r file <&3; do
> something with "$file" # be sure to quote "$file"
> done 3< list.txt
> (if your read doesn't have the "-r" option, either make another
> assumption that filenames don't contain backslashes, or use:
>
> exec 3<&0
> sed 's/\\/&&/g' < list.txt |
> while IFS= read file; do
> something with "$file" <&3 3<&-
> done
> )
>
> 2-
>
> IFS="
> " # set the internal field separator to the newline character
> # instead of the default "<space><tab><NL>".
>
> set -f # disable filename generation (or make the assumption that
> # filenames don't contain *, [ or ? characters (maybe more
> # depending on your shell)).
>
> for file in $(cat < list.txt); do
> something with "$file" # it's less a problem if you forget to
> # quote $file here.
> done
>
> Now, beware that there are things you can do before building
> this list.txt. There are other ways to store filenames. For
> instance, you have the positionnal parameters.
>
> with:
> set -- ./*.txt
>
> you have the list of txt files in the current directory, and no
> problem with weird characters. Looping through them is just a
> matter of:
>
> for file
> do something with "$file"
> done
>
> You can also escape the separator. For instance, with
>
> find . -exec sh -c 'printf %s\\n "$1" | sed -n '"':1
> \$!{N;b1
> }
> s/|/|p/g;s/\n/|n/g;p'" '{}' '{}' \;
>
> instead of
>
> find . -print
>
> you have the same list of files except that the \n in filenames
> are changed to "|n" and the "|" to "|p". So that you're sure
> there's one filename per line and you have to convert back "|n"
> to "\n" and "|p" to "|" before refering to the file.
>
> 19. how to change my login shell to zsh?
[XXX This should be "how to change my login shell to shell X",
with a pointer to Brian Blackmore's "UNIX shell differences and
how to change your shell":
http://www.faqs.org/faqs/unix-faq/shell/shell-differences/
]
> 20. when to use shells instead of perl/python/ruby/tcl...
[XXX I'd prefer
Advantages of using shells instead of perl/python/ruby/Tcl...
> a. Portability
>
> In many cases it can't be assumed that perl/python/etc are
> installed on the target machine. Many customer sites do not
> allow installation of such things. In cases like this, writing
> a shell script is more likely to be successful. In the extreme,
> writing a pure Bourne shell script is most likely to succeed.
>
> b. Maintainability
>
> If the script is one which serves some important purpose, and
> will need to be maintained after you get promoted, it's more
> likely that a maintainer can be found for a shell script than
> for other scripting languages (especially less used ones such
> as ruby, rexx, etc).
>
> c. Policy
>
> Sometimes you're just told what to use :-)
20b When not to use shells?
There are problems the typical unix shells are not
well suited for. Other programming languages should
be considered in the following cases:
o handling of binary data or files is required
o speed is of utmost importance
o a GUI is needed
[XXX more?]
Most of the problems shells have with the topics listed
above can be solved by using a specialized version of
a shell (GUI: dtksh) or a particular helper program,
but in general other languages should be considered, too.
The unix shell is a powerful programming language,
but it's just a tool to solve a particular problem
the programmer may have. While the shell may be the hammer
in the unix toolbox, it should not be used to drive
screws into the wall.
> 21. why shouldn't I use csh?
>
> http://www.softlab.ntua.gr/facilities/documentation/unix/grymoire/CshTop10.txt
> http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/
>
> 22. why is shell programming considered harmful?
This may be a point of discussion, but it's not
an FAQ. Is it?
> 23. what shell should I use for scripting?
> 24. how to reverse a file?
>
> Non-standard commands to do so are GNU tac and "tail -r". sed
> '1!G;h;$!d' is subject to sed limitation on the size of its hold
> space and is generally slow.
>
> The awk equivalent would be:
>
> awk '{l[n++]=$0}END{while(n--)print l[n]}'
> It stores the whole file in memory.
>
> The best approach in terms of efficiency portability and resource
> cosumption seems to be:
>
> cat -n | sort -rn | cut -f2-
>
> "cat -n" is not POSIX but appears to be fairly
> portable. Alternatives are "grep -n '^'", "awk '{print NR,$0}'",
> "nl" can't be used as it processes page headings.
>
> 25. how to remove last 10 lines?
>
> 26. how to get a file size, a file modification time?
> 27. how to get a process id by process argv[0]?
> 28. how to get a script to update my current environment?
> 29. how to find files less than 15 minute old?
> 30. how can I know wether my script is portable?
> 31 how do I rename *.foo to *.bar?
> 32. how to redirect stdout to file1 stderr to file2 while still
> seeing them on screen?
> 33. how to loop through *.txt files and treat the case when
> there's no such file (+ dotfile issue).
> 34. why isn't var set in "cmd | read var"
> 35. how to use shell variables in awk scripts
> 36. date manipulations
> 37. how to input the user with a timeout?
> 38. how to input user for only one char?
> 39. why isn't my .profile read?
> 40. known incompatibilities/limitations in sed/grep/awk/...
> 41. why do I get "[5" not found in "[$1 -eq 2]"?
> 42. how to deal with dot files?
> 43 why is zsh the best shell? ;)
> 44. How to exactly display the content of $var (with a \n appended).
>
> A: on POSIX systems or with shells with builtin printf (bash2,
> ksh93, zsh4.1, dash...)
>
> printf '%s\n' "$var"
>
> (except for memory/environment full errors, should be expected
> to work at least if $var is not longer than LINE_MAX (supposed
> to be at least _POSIX2_LINE_MAX == 2048), no harcoded limits in
> zsh/ksh/bash/dash builtins)
>
> ksh, zsh:
> print -r -- "$var"
>
> zsh:
> echo -E - "$var"
>
> Other bourne like shells:
>
> cat << EOF
> $var
> EOF
> (creates a temporary file and forks a process)
>
> expr "x$var" : 'x\(.*\)'
> (limited to 126 characters with some exprs, may return a
> non-null exit code).
>
> With ash:
> (unset a; ${a?$var}) 2>&1
>
> 45. How to exactly display the content of $var (without a \n
> appended).
>
> printf %s "$var" # posix
> print -rn -- "$var" # zsh/ksh
> echo -nE - "$var" # zsh
>
> awk 'NR>1{print ""}{printf("%s",$0)}' << EOF
> $var
> EOF
>
> (with awk limitations [line length and number of fields])
>
Heiner
-- ___ _ / __| |_ _____ _____ _ _ Heiner STEVEN <heiner.steven@nexgo.de> \__ \ _/ -_) V / -_) ' \ Shell Script Programmers: visit |___/\__\___|\_/\___|_||_| http://www.shelldorado.com/
- Next message: Scott Coffland: "grep search on command history file does not work on Tru64 Unix"
- Previous message: Chris F.A. Johnson: "Re: kshell: var. within a var."
- In reply to: Joe Halpin: "Re: Call for input on comp.unix.shell FAQ"
- Next in thread: Stephane CHAZELAS: "Re: Call for input on comp.unix.shell FAQ"
- Reply: Stephane CHAZELAS: "Re: Call for input on comp.unix.shell FAQ"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
|