From KRayWiki
Jump to navigation Jump to search
See Also 

Workarounds for various deviations between Linux and SCO OpenServer 5.0.7 commands.

External Links

  1. Rosetta Stone for Unix

Bourne vs BASH

!: not found

The following if statement results in a !: not found error:

if ! grep regex /path/to/file >/dev/null 2>&1 then echo something else fi

A workaround is possible:

if { grep regex /path/to/file >/dev/null 2>&1; test ${?} -ne 0; } then echo something else fi

Parse strings with a regular expression

  1. expr's colon operation offers limited string matching functionality.
    • Can make up for missing variable manipulation operators provided by BASH.
    • Sometimes this can facilitate avoiding use of echo, a pipe, and another command like sed.
    • Caveats:
      1. Regular expressions are simplified
        • ? is not understood as 0 or 1 matches (but this is also true of the Linux versions)
        • Regular expressions are implicitly rooted at the beginning of the string (^ is not special).
      2. expr arithmetic operators in the first argument may result in expr: syntax error
        i.e. expr "/" : '\(/\)' results in a syntax error.
        • Workaround: expr "X/" : 'X\(/\)' does not result in a syntax error.
        • Linux expr does not seem to have the same parsing issue as the SCO version.
      3. Arguments that contain whitespace require quoting. use of \(...\) can be finicky.
        The backslash is a critical part of the syntax. Either:
        • Use apostrophes to quote the regular expression to protect the backslashes, or,
        • Escape the backslashes i.e. expr X/ : X\\\(/\\\)

Built-in Alternatives

awk : limited input line length

Input line length is restricted to about 3000 characters. This has practical concerns as files like /etc/group may have lines that exceed this length.

A workaround is to use other tools when there is a possibility of hitting this limit. perl scripts can embed into shell scripts similar to awk script embedding. A non-trivial example is illustrated on the OS-SCO-Linux page.

awk -v Variable Restrictions

Assigned Value Length is Restricted

A value assigned to a variable via the -v command line switch is limited to 400 characters in length. If this limit is exceeded, the error message produced is 'awk: string StringText... too long', where 'StringText' is the beginning of the assigned value. See: OS-SCO-KnownIssues&action#awk_:_limited_-v_variable_length

Backslash Escapes are not Supported

Whereas GNU awk can accept backslash escapes for carriage-return, line-feed, and form-feed characters, SCO's native awk cannot. For example:

$ awk -v RS="[\r]*[\f\n]+[\r]*" ' { print } ' LO 
awk: input record `
SULPHUR SPRINGS I....' too long
source line 1 of program << { print } >>

tr or sed are useful for clearing unwanted characters.

sed offers the most flexible replacement options as it accepts regular expressions.
SCO's version is very limited in its ability to interpret backslash escapes. Control characters are entered into the pattern verbatim.
For example, to place a carriage-return in a pattern, type <Ctrl>+<V><Ctrl>+<M> into it.
tr can replace characters, delete (-d) characters, and compress (-s) series of identical characters.

The issue with backslash escapes may be more simple. SCO's awk generally rejects literal line-feeds in strings. For example:

# Non-zero PAGEHEAD indicates report header processing active.
awk: newline in string \LO-M.txt...
at line 4 of program << \
BEGIN ... >>
context is
REM = " \ >>>

awk delete array [subscript]

It was a surprise to find SCO Openserver 5.0.7 awk calls delete array a syntax error though the man page says the subscript is optional.

$ awk 'BEGIN { A[1] = 0; delete A; }' 
awk: Syntax error  
at line 1 of program << BEGIN { A[1] = 0; de ... >> 
context is 
BEGIN { A[1] = 0; delete >>> A; <<< 
awk: illegal statement 
at line 1 of program << BEGIN { A[1] = 0; de ... >> 

It was more surprising to find that delete array[subscript], while not shown as an error, also did not work, and that many variants on array[subscript] = "" were equally ineffective.

/usr/bin/awk -> /opt/K/SCO/Unix/5.0.7Hw/usr/bin/awk 

The work around from https://unix.stackexchange.com/questions/147957/delete-an-array-in-awk

split("", array, ":") 

awk gensub()

Whereas GNU awk implements a handy gensub() function that performs recursive or non-recursive substitutions and handily returns the result without modifying the original, old versions of awk do not. It is simple enough to workaround this by converting gensub() references in the following manner:

Non-recursive calls are identified by having either "" or "1" as the third argument:

edited_value = gensub(/regex/, "substitution", "1", source_value) 

Non-recursive workaround:

temporary_value = source_value; 
edited_value = sub(/regex/, "substitution", temporary_value); 

Recursive calls are identified by having "g" as the third argument:

edited_value = gensub(/regex/, "substitution", "g", source_value) 

Recursive workaround:

temporary_value = source_value; 
edited_value = gsub(/regex/, "substitution", temporary_value); 

date: -d illegal option

$ date -d "2019/02/13 16:00:59 UTC" 
date: -d illegal option

A perl, one-liner workaround:

$ perl -se 'use Date::Parse; use POSIX; print strftime("%c\n", localtime(str2time($Time)));' -- -Time="2019/02/13 16:00:59 UTC"
Wed Feb 13 10:00:59 2019

dos2unix / unix2dos

$ dtox / xtod 
CRLF/LF text file line delimiter translation.
dtox / xtod are filters, so use output redirection to write to a file other than the original file.


$ ex 
a text editor
The -c command-line argument implementation varies from system to system.
On SCO Unix where vi is not supplied by gvim:
$ ls -l `which ex`
lrwxrwxrwx 1 root root 34 May 5 2008 /usr/bin/ex -> /opt/K/SCO/Unix/5.0.7Hw/usr/bin/vi
$ man ex
-c command
Execute the specified command at start up. Individual
commands can be separated by vertical bar characters
When ex is a gvim component:
$ man ex
−c command
Specify an initial command to be executed in the first edit
buffer loaded from an existing file (see the EXTENDED
DESCRIPTION section). Implementations may support more than
a single −c option. In such implementations, the specified
commands shall be executed in the order specified on the com‐
mand line.
The SCO variant DOES NOT support multiple -c arguments, but documents that multiple commands are possible via vertical bar delimiters.
The gvim variant DOES implement the vertical bar delimiter, even though it is not documented in the associated man page.
For cross-platform compatibility, use the vertical bar delimiter rather than multiple -c arguments.


$ find . -maxdepth 0 
List only items in the current directory without traversing into a sub-directory.
Increase the number to increase the number of levels below the current directory to traverse.
Whereas find on Linux supports -maxdepth, find SCO version of find does not.
For the specific case of $ find . -maxdepth 0, the following is a possible workaround:
$ find . -level 0 | grep -v '/'
The issue is that while -maxdepth references the current directory, -level refers to the content of a sub-directory of the current folder.


$ id -Gn 
List a user's /etc/group memberships.
Whereas id -Gn and groups on Linux produce identical, one-line output, the SCO command outputs multiple lines of text that lists certain group memberships on multiple lines.
See groups under Alternative Linux Workarounds for other solutions that more closely emulate the output of the Linux command.


GNU's install offers a significantly different set of command-line arguments than the SCO OpenServer 5.0.7 version. On SCO OpenServer 5.0.7, some switches are not supported. For example:

$ sudo install -p -m 775 -o root -g sys "sdi-library.sh" "/usr/local/bin" 
/etc/install: ERROR: Illegal option -- p

Other switches are supported but may not provide similar functionality. For example, on Linux, -o specifies the installed file's owner, but on SCO OpenServer 5.0.7, this switch backs up a pre-existing file by renaming it with an "OLD" prefix.

ltrace / strace

$ truss 

sed with \n

Whereas GNU's sed can split an input line into multiple output line, SCO's native sed command cannot.

$ echo split:me | sed -e "s/:/\n/g" 

SCO's tr command can split input lines. For example:

$ echo split:me | tr ":" "\n" 
Caveat: Whereas a GNU sed script could replace a single character with multiple characters, tr replaces characters on a one-for-one basis.

su -l / su --login

$ su - 
-, -l, and --login are synonyms on Linux.

test: unknown operator -nt

$ test file -nt /path/to/reference 
test: unknown operator -nt
$ test -n "`find . -name file -newer /path/to/reference 2>/dev/null`" 

test: unknown operator -ot

$ test file -ot /path/to/reference 
test: unknown operator -ot
$ test -n "`find /path/to -name reference -newer file 2>/dev/null`" 

touch: ERROR: Illegal option -- d

$ touch -d "Wed Dec 31 18:00:00 1969" path/to/file 
touch: ERROR: Illegal option -- d

A workaround is:

$ perl -se 'use Date::Parse; use POSIX; utime(str2time($Time), str2time($Time), $File)' -- -Time="2019/02/13 16:00:59" -File=file 


$ id -un 
Output is identical to that of the Linux command.
$ who am i 
Output is significantly different than that of the Linux command.

Alternative Workarounds


A viable workaround produces output similar to Linux:

#!/bin/sh perl -s -- - -U="$1" -G=`id -gn $1` <<-'END-OF-SCRIPT' printf '%s : %s ', $U, $G; $regex = '(^|[,])'.$U.'([,]|$)'; open(GROUPS, '<', "/etc/group"); line: while (<GROUPS>) { @Field = split(/[:]/, $_, -1); print "$Field[0] " if $Field[3] =~ m/$regex/; } print "\n"; print "$regex\n"; END-OF-SCRIPT

A workaround was originally developed using awk, but SCO's awk has a line length limit (3000 characters?) exceeded by some system /etc/group files.