ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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 mknasosnames2.sh, which it's job is to create standard directories for each known operating system. It's code in Windows XP:
Code:
@ECHO OFF
ECHO Making Directories for Each Operating System...
MKDIR OS
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
:mktypes
IF "%~1" == "(none)" GOTO mktypes_done
CALL mknastypes3 %1
GOTO mktypes_done
:mktypes_done
EXIT /B 0
:done
It's Linux code so far:
Code:
#! /bin/sh
echo Making directories for each operating system...
mkdir OS
cat /etc/settings/Operating_Systems/osnames.sdr | while read -a line
do
echo ${line[0]}
echo ${line[1]}
cat ${line[1]} | while read -a line2
do
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
done
done
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.
[root@c-des-main1-rec standard_scripts]# . ./mknasosnames2.sh
Making directories for each operating system...
mkdir: cannot create directory `OS': File exists
DOS
/etc/settings/Operating_Systems/dos.sdr
: No such file or directoryg_Systems/dos.sdr
LINUX
/etc/settings/Operating_Systems/linux/types.sdr
: No such file or directoryg_Systems/linux/types.sdr
WINDOWS
/etc/settings/Operating_Systems/windows/types.sdr
: No such file or directoryg_Systems/windows/types.sdr
[root@c-des-main1-rec standard_scripts]#
Last edited by des_a; 02-04-2013 at 05:36 AM.
Reason: Bad copy and paste.
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.
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.
Last edited by David the H.; 02-04-2013 at 12:57 PM.
Reason: minor rewording
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/BabyPhotoStarGalleryGetImagesAslist.sh); 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/BabyPhotoStarGalleryGetImagesAslist.sh where f[N] is lines from file
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.
DOS /etc/settings/Operating_Systems/dos.sdr
LINUX /etc/settings/Operating_Systems/linux/types.sdr
WINDOWS /etc/settings/Operating_Systems/windows/types.sdr
95 (none)
98 (none)
XP /etc/settings/Operating_Systems/windows/XP.sdr
/etc/settings/Operating_Systems/windows/XP.sdr
Code:
HOME
PRO
MCE
These are the files I'm trying to parse. I did try it with the following format:
Code:
while read -a line2
do
...
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.
... 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?
#!/bin/sh
echo Making directories for each operating system...
mkdir -p OS
cd OS # did you want this?
while read -a line
do
echo ${line[0]}
echo ${line[1]}
while read -a line2
do
if [ -d ${line2[0]} ]; then
echo There\'s already a directory named ${line2[0]}
else
echo Creating ${line2[0]}...
mkdir ${line2[0]}
cd ${line2[0]}
cd ..
fi
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]}
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.