-   Programming (
-   -   Translating Standard Scripts to Linux (

des_a 02-04-2013 01:10 AM

Translating Standard Scripts to Linux
I've been translating my code from Windows XP DOS BATCH files to Linux BASH shell scripts. I've run into a problem from this script. I'm having trouble parsing the database I've created, which tells Linux how to create a set of directories in this case.

The I'm on, which it's job is to create standard directories for each known operating system. It's code in Windows XP:



ECHO Making Directories for Each Operating System...

FOR /F "tokens=* delims=$n" %%A IN (C:\SETTINGS\Operating_Systems\osnames.sdr) DO (
 FOR /F "tokens=1,* delims=        " %%B IN ("%%A") DO (
  ECHO Creating %%B...
  IF EXIST "%%B" ECHO There's already a directory named %%B!
  MKDIR ".\%%B"

  CD ".\%%B"
  CALL :mktypes "%%C"
  CD ..
GOTO done

 IF "%~1" == "(none)" GOTO mktypes_done

 CALL mknastypes3 %1
 GOTO mktypes_done

  EXIT /B 0


It's Linux code so far:


#! /bin/sh

echo Making directories for each operating system...
mkdir OS

cat /etc/settings/Operating_Systems/osnames.sdr | while read -a line
 echo ${line[0]}
 echo ${line[1]}
 cat ${line[1]} | while read -a line2
  echo Creating ${line[0]}...
#  if [ -f $line2[0] ]; then 
#  echo There\'s already a directory named $line2[0]
#  else
#  mkdir $line2[0]

#  cd $line2[0]
#  cd ..
#  fi

It fails on the second while loop, currently.

des_a 02-04-2013 01:19 AM

By the way, what my standard scripts are is this: Any OS that can support the standard scripts can be used on this network, I know this will work in Linux, I just don't know how yet.

dive 02-04-2013 04:38 AM

If you're testing for a directory, use -d not -f in your test.

# if [ -d $line2[0] ]; then

des_a 02-04-2013 06:35 AM

This is it's output:


[root@c-des-main1-rec standard_scripts]# . ./
Making directories for each operating system...
mkdir: cannot create directory `OS': File exists
: No such file or directoryg_Systems/dos.sdr
: No such file or directoryg_Systems/linux/types.sdr
: No such file or directoryg_Systems/windows/types.sdr
[root@c-des-main1-rec standard_scripts]#

des_a 02-04-2013 06:38 AM

Thanks. I'll use -d instead of -f. But with the output, now you see the problem. I'd tried a for loop, and it does the same thing. Appearently, it's comming from the cat command.

---------- Post added 02-04-13 at 03:38 AM ----------

If it really sees that shortened version of what it reports, it has reason to complain, but I want it to see the whole path, which I put in the file.

David the H. 02-04-2013 01:44 PM

This page has some tips about converting DOS batch files to bash.

But if you really want to code "standard" scripts, then you have to restrict all of your code to what's available in the POSIX standard. When you run a script with "#!/bin/sh" at the top, it will be interpreted as such, even if the underlying interpreter is actually bash or another shell.

Conversely, to get the full set of bash features, you have to use #!/bin/bash.

POSIX doesn't have many of the useful modern features that are available to bash, such as arrays. See this page for bash-specific commands and their equivalents.

Note: If your script does include things like arrays, and they seem to work, that's only because the system is still set to use bash (or a similar shell) to do the interpreting. Since arrays are not counter to POSIX, but just undefined by it, there's nothing keeping a shell from interpreting them if it wants to. But if, for example, the system was using dash instead (a strictly complying shell), it would break. All /bin/sh says is that, if a script is coded according to POSIX, it will run. It doesn't try to force compliance to it.

In fact, one of the best ways to test that your script is POSIX-compliant is to use #!/bin/dash as your shebang. If it runs in dash, it should run anywhere.

Incidentally, I see several errors in the above script. Unquoted variables, improperly formatted array expansions, Useless Use Of Cat. But maybe I should wait for you to clarify whether you actually need POSIX or not, or whether a bash-compatible script would do (it is available standard on pretty much every Linux distro, after all). The latter would certainly be much more convenient.

PS: You also really need to supply us with a sample of the input. We need to see what the files that it's processing hold.

sunnydrake 02-04-2013 01:51 PM

really.. it's hard to say how to fix it if you don't say what's actually wrong.. second loop is wrong it like my pc is broken fix it.. for file read i use
for f in $(cat -s ~/bin/; do echo "LINE".$f;done;
but there is a problem f is each word(1) separated by spaces
so to read lines is better to use readarray f < ~/bin/ where f[N] is lines from file

David the H. 02-04-2013 02:44 PM


Please Do not Read Lines With For. Always use a while+read loop instead.

How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?

readarray/mapfile is another safe option, but probably not suitable if the input file is very large. It's also a bash-specific extension (available since 4.0), and not at all portable.

And do please use ***[code][/code]*** tags around your code and data, to preserve the original formatting and to improve readability.

dive 02-04-2013 04:46 PM

For some reason it isn't reading line2 correctly when it cats ${line[1]}. Cat you post a bit of /etc/settings/Operating_Systems/dos.sdr ?

I would tend to use something like:

while read -a line2
done < ${line[1]}

in these situations.

Also, if you use mkdir with the -p (make parent) flag it will surpress the already exists warnings.

schneidz 02-04-2013 04:54 PM

can the op please post a few lines of the input file and what they are expecting the output to be ?

des_a 02-04-2013 08:44 PM

I'll post the files.

des_a 02-04-2013 09:00 PM


DOS        /etc/settings/Operating_Systems/dos.sdr
LINUX  /etc/settings/Operating_Systems/linux/types.sdr
WINDOWS        /etc/settings/Operating_Systems/windows/types.sdr


FreeDOS        (none)
PC-DOS        (none)
MS-DOS        (none)


Mandrake        /etc/settings/Operating_Systems/linux/Mandrake.sdr
Mandriva        /etc/settings/Operating_Systems/linux/Mandriva.sdr





95        (none)
98        (none)
XP        /etc/settings/Operating_Systems/windows/XP.sdr



These are the files I'm trying to parse. I did try it with the following format:


while read -a line2
done < ${line[1]}

...and this had exactly the same result.

Let me know if I need to explain the syntax of any of these files. Also note that they probably need to be updated to contain my latest information, however, that was not my first priority. It's the same syntax I have on Windows XP, except with a Linux path name instead of a Windows path name. The Windows code works.

des_a 02-04-2013 09:01 PM

You can also see that the code is still not complete yet, when it gets to the second loop working, but that's what I'm stuck on for now.

sundialsvcs 02-04-2013 11:42 PM

Interesting thought ...

... has no one in Linux-land ever tackled the ("if I on-ly had a brain...") ;) problem of dealing with DOS batch-files? Is it really true that no one ever wrote a command that could "gracefully and graciously" (of course...) accept DOS batch-files as input, and "have a good college try" at running them?

Casually googling, I didn't find one (yet), but ... it seems so obvious. Really?

You mean, I can't do: #!/bin/ihavenobrain ?? ;)

dive 02-04-2013 11:46 PM

This works for me.



echo Making directories for each operating system...
mkdir -p OS
cd OS # did you want this?

while read -a line
    echo ${line[0]}
    echo ${line[1]}
    while read -a line2
        if [ -d ${line2[0]} ]; then
            echo There\'s already a directory named ${line2[0]}
            echo Creating ${line2[0]}...
            mkdir ${line2[0]}
            cd ${line2[0]}
            cd ..
    done < ${line[1]}

done < /etc/settings/Operating_Systems/osnames.sdr

ls OS
95/ 98/ FreeDOS/ MS-DOS/ Mandrake/ Mandriva/ PC-DOS/ XP/

Note that I've changed all the $line2[0] to ${line2[0]}

All times are GMT -5. The time now is 03:15 AM.