Run a UNIX command on each file in a directroy

28 03 2007

I keep having to look it up at random times, so I though I would post it here.

First there is the basic for loop, this however has some drawbacks, namely not being able to handle files with spaces in the filename, it sees a space as a newline and treats each individual part of the filename as an individual file. For the file “Sample File.txt” the the updating timestamp output is printed fine for the one file “Updating Sample File.txt”, but the touch command will execute on multiple files “Sample” and “File.txt”.
for file in *; do echo "Updating timestamp for $file"; touch "$file"; done

Using find with xargs, this only seems to be able to handle one command at a time (unless you bother to write a script for it). It puts all the commands on one line, rather than executing the command multiple times. It also doesn’t support more than one command, so echoing the message for each individual file seems impossible and it won’t work on commands unless they accept multiple filenames.
find . -print0 | xargs -0 touch

The next one is to use find with the -exec argument and some odd parameters, this allows for multiple command and spaces :):
find . -exec echo "Updating timestamp for" {} \&\& touch {} \;

Finally if you want something thats a bit nicer for use in scripts you can use read to stop the splitting of filenames:
find . | while read FILE; do
echo "Updating timestamp for $FILE"
touch "$FILE"

QEMU for DOS abandonware under Linux

17 03 2007

EDIT: System Shock 1 is now working for me under kqemu, see end.

I decided I wanted to play some System Shock 1, unfortunately the game being several years old it no longer runs on modern system. There are emulation solutions such as DosBox (slow) and VDMSound (Windows only, I use Linux) however these have various flaws, bugs and compatibility issues, and even more problems when trying to run System Shock in particular. Unfortunately System Shock 1 wouldn’t work with sound but other games hopefully run better, the sound did work in Windows 3.1 🙂

So I decided that I would give QEMU a try, its a nice fast Emulator since it also supports virtualization it can run at almost native speeds. Works on both Windows and Linux. And since we are emulating the entire computer rather than trying to intemperate the OS specific instruction sets we can get close to compatibility. We do however need to install an OS.

These instructions are Linux based, however Windows also runs qemu so a lot of it is feasible, the main problem would be using the loopback floppy images.

First of all we need our OS, a copy of DOS, there are a few free choices around such as FreeDOS and OpenDOS. Unfortunately these are not 100% compatible depending on what software you are running you will have mixed results, apparently System Shock has problems running on FreeDOS due to some custom memory management by the developers and I would guess the other clones would have similar issues also.

There is also MS-DOS 7.1 which was the DOS shipped with Windows 98 repackaged, apparently that has some compatibility issues also.

I decided to use MS-DOS 6.22, many people have an old copy of the floppy disks lying around. It’s probably not legal to download although googling for shows many people think otherwise 😉

Once you have gotten your copy of Dos, you will either have real floppies or probably IMA disk images (they might arrive in self extracting archives exe’s, under Linux you can just use unzip to extract the files form the exe, wine would probally work too) , these images are supposedly in a DiskWrite format however they appear to be just basic binary dumps of the floppies the same you would get from running a ‘dd if=/dev/fda of=floppy.img’. ‘file DOSDISK1.IMA’ shows them as “DOSDISK1.IMA: DOS floppy 1440k, x86 hard disk boot sector”. IMZ files are just zipped IMA files so just unzip them.

If you are using original floppies, I recommend converting them to images with dd as images are a lot faster and floppies are fairly unreliable, its also handy to have backups.

The next step will be to crate a image for the File System:
qemu-img create -f qcow msdos.img 20G

This will create a 20G image, because we are using the qcow format the image file will only take the amount of space as the data we install onto it. 20G is excessive, a FAT16 partition can’t use that much space but its not using any disk space so the size is irreverent and you don’t want to give yourself to little space as you would need to resize the partition or probably format and start again, the other format choice raw is more compatible but for the FAT file system it will take the entire amount of space you give it. (Trying the new qcow2 format might also be an idea, my version of qemu didn’t have it as an option though)

If you are using disk images you will need to be able to access them as devices, run the following as root to bind them to /dev/loop0
losetup /dev/loop0 DOSDISK1.IMA

Now we need to boot the system with the qemu command (the faster ‘kvm’, Linux Kernal Virtualization Module version didn’t boot dos for me and crashed when Dos tried to initialize HIMEM (or directly after), I don’t have kqemu running so it might be worth disabling that if you have it installed and encounter problems. Stock qemu is slower but this stuff was designed to run on 33MHz so I don’t think there will be to much speed loss from the emulation layer, you can also use your real floppy drive with /dev/fda instead of /dev/loop0.
qemu -soundhw sb16 -cdrom /dev/cdrom -fda /dev/loop0 -hda ./msdos.img -boot a

You should get the MS-DOS 6.22 Setup screen, following the prompts it should partition and format the hard drive, reboot and then install.

When the setup asks for Disk2, if you are using images press ctrl+alt+2 and you will be in the QEMU monitor mode. Type eject fda This disconnects Qemu from the loopback floppy image so you can disconnect the image from /dev/loop0.
Pull up a terminal and losetup -d /dev/loop0

Now you need to bind disk 2 to loop0:
losetup /dev/loop0 DOSDISK2.IMA

Go back to QEMU and type change fda /dev/loop0

Press ctrl+alt+1 to resume the simulation and continue the Dos install procedure. Repeat for Disc 3.

When DOS has finished installing it will attempt to boot from A again, just remove the ‘-boot a’ line to make it boot from the hard drive and you should end up in a dos prompt.

Next is installing stuff. In order to transfer stuff from your local file system to the dos image, you need to run with the flag ‘-hdb fat:/your/driectory’, when I tried this I needed to be root. This will add an extra drive D: that maps to the directory specified, this allows you to put drivers and games in a directory and copy/install them onto the image under DOS. Otherwise you could try converting the image to a raw format (it will take the entire size of the image then), mounting on a loopback and copying the files across under Linux.

You will want to track down the sb16 drivers to get sound working, google for “sbbasic.exe” and install the drivers under dos. And for mouse drivers CTMOUSE works fine (its from FreeDos) otherwise any other PS/2 dos mouse driver will do. You might want to add the mouse driver to your autoexec.bat so you don’t have to run it every boot

There are also some video card drivers that allow Windows 3.1 to run in higher resolutions. Google “”

Now you can install and run games/programs.

Unfortunately System Shock doesn’t detect the audio correctly (It works fine in Win 3.1). But hopefully other games will work better. EDIT: System Shock 1 is now working for me under kqemu with sound. Autodetect does fail sometimes but if you try several times it works. I’ve noticed that SoundBlaster Pro doesn’t crackle like SoundBlaster 16 does. Use Adlib for the music. Sometimes the sound isn’t detected by the game either so you might need to restart if there if you hear nothing on the main menu. When trying to install the SoundBlaster 16 drivers I was getting a “Program too big to fit in memory” error, I think this was caused by having ‘–swhardware all’ rather than just ‘–swhardware sb16’. I also had problems with it freezing and giving me a blackscreen leaving the mouse locked to the window (ctrl+alt not doing anything) and even after killing qemu from another console the mouse was not working requiring xorg to be restarted with ctrl+alt+backspace. I don’t know what was causing that but making a new hdd image and installing from scratch fixed it, maybe not having a copy of Windows 3.1 installed helped.

Windows for Workgroups 3.11 under QEMU