Friday, April 27, 2012

back and forward in bash

One of the things I like about window-based file-browsing is the back and forward buttons...

So here're my bash scripts. Feel free to use them. If you find them handy buy me a beer (or post a comment)! Unless, of course, you're planning to profit off 'em, then you can and should buy me a brewery after asking my permission.

There are four files. mycd.sh, back.sh, fwd.sh, and mycdlist.sh
They have to be run in a way I just learned about today (in order to export the variables back to the running bash session) using "source" or "." (explained further, below)

I have added the following to my ~/.bash_profile:
####### For scripts, etc. that need to export variables back to bash ######
# create the script as normal
# all variables in the script are set when returning to bash...
# so best to use this only when all variables are safe...
# (Maybe call another script from the one that's exporting variables?)
# either call them as ". script.sh", "source script.sh" or add them here:
# alias script="source script.sh"
alias cd="source ~/myexecs/mycd.sh"
alias back="source ~/myexecs/back.sh"
alias fwd="source ~/myexecs/fwd.sh"
alias cdls="source ~/myexecs/mycdlist.sh"

So, I have overridden bash's "cd" command with my own... we'll see how safe this is with some testing, but currently it seems to work great. (Thinking about using this method for rm to move things to the trash... not sure yet. The trash is kinda annoying sometimes. Or at least to require a verification beforehand...)

mycd.sh is called just like a normal "cd" command, and should, in fact, work identically, with the addition of creating a variable for history...
back.sh is a simple command, has no arguments, steps one step back in the history written by mycd.sh. As set up in my bash-profile, it's called by typing "back" at the command prompt
fwd.sh does the opposite (called by typing "fwd")
mycdlist.sh lists the history and shows where you are currently (no arguments). I call it by "cdls" and its output looks like this (after calling "back" once):
MYCDPOS='1'
MYCDLASTPOS='2'
[0]='/Users/meh'
[1]='/Users/meh/Another Directory' <-- You Are Here [2]='/Users/meh/Another Directory/AndYetAnother' Here are the files (Don't forget to chmod +x). Oh, one thing... I'm not a genius, and lots of what's in here is new to me as of the past few hours... it hasn't been tested for longer than that. I'll post updates if I revise these. ******** mycd.sh: #!/bin/bash if [ "$MYCDPOS" == "" ] ; then MYCDLASTPOS=0 MYCDPOS=0 MYCDHIST[0]="$PWD" # Make these available to scripts that are called WITHOUT "source" # (Actually, I don't think this works... mycdlist was difficult with this assumption) export MYCDLASTPOS export MYCDPOS export MYCDHIST fi MYCDPOS=$(( MYCDPOS + 1 )) if [ $(( MYCDLASTPOS >= $MYCDPOS )) -eq 1 ] ; then
echo "- Overwriting history -"
fi


MYCDLASTPOS=$MYCDPOS

#echo "$@"

#cd "$@"
### Stolen from /usr/bin/cd from: $FreeBSD: src/usr.bin/alias/generic.sh,v 1.2 2005/10/24 22:32:19 cperciva Exp $
#builtin ${0##*/} ${1+"$@"}
# Doesn't work, I assume, because this is technically mycd.sh even though it's aliased as cd
builtin cd ${1+"$@"}

MYCDHIST[$MYCDPOS]="$PWD"


*************** back.sh:


#!/bin/bash

# Check if there's any history yet...
if [ "$MYCDPOS" == "" ] ; then
echo "- No history yet -"

# Check if there's still history to enter
elif [ $((MYCDPOS - 1)) -lt 0 ] ; then
echo "- End of history -"

#This shouldn't happen in the back case, but it's still a decent test...
elif [ "${MYCDHIST[$((MYCDPOS - 1))]}" != "" ] ; then

MYCDPOS=$(( MYCDPOS - 1 ))

# Check if we're entering old history...
# This happens when back is used a couple times
# then mycd is used, then fwd is used...
# mycd will place new entries beginning at the last
# position used (via back/forward),
# which might overwrite a history entry,
# but it doesn't clear all entries
# This doesn't matter, but it might be helpful to know
if [ $((MYCDPOS > MYCDLASTPOS)) -eq 1 ] ; then
echo "- In old history -"
fi

echo "'${MYCDHIST[$MYCDPOS]}'"
builtin cd "${MYCDHIST[$MYCDPOS]}"

# WTF?
else
echo "- WTF? -"
fi




***************** fwd.sh:


#!/bin/bash

# Check if there's any history yet...
if [ "$MYCDPOS" == "" ] ; then
echo "- No history yet -"

# Check if there's still history to enter
elif [ "${MYCDHIST[$((MYCDPOS + 1))]}" != "" ] ; then

MYCDPOS=$(( MYCDPOS + 1 ))

# Check if we're entering old history...
# This happens when back is used a couple times
# then mycd is used, then fwd is used...
# mycd will place new entries beginning at the last
# position used (via back/forward),
# which might overwrite a history entry,
# but it doesn't clear all entries
# This doesn't matter, but it might be helpful to know
if [ $((MYCDPOS > MYCDLASTPOS)) -eq 1 ] ; then
echo "- Entering old history -"
fi

echo "'${MYCDHIST[$MYCDPOS]}'"
builtin cd "${MYCDHIST[$MYCDPOS]}"

# Reached the end of the history
else
echo "- End of history -"
fi


***************** mycdlist.sh:


#!/bin/bash

MYCDTEMPitemNum=0

echo "MYCDPOS='$MYCDPOS'"
echo "MYCDLASTPOS='$MYCDLASTPOS'"
#Allegedly (and experimentally) there's no way to export arrays
#Thus mycdlist.sh must also be called via "source" or "."
#even though it's only *reading* the variables which are shown
#in bash when you type "set." I'm no export expert, this is kinda voodoo to me.

#echo "MYCDHIST="

if [ "$MYCDPOS" != "" ] ; then
while [ 1 ]
do
MYCDTEMPitem="${MYCDHIST[$MYCDTEMPitemNum]}"
# echo "item='$MYCDTEMPitem'"
if [ "$MYCDTEMPitem" == "" ] ; then
break
else
if [ $MYCDTEMPitemNum -eq $MYCDPOS ] ; then
echo "[$MYCDTEMPitemNum]='$MYCDTEMPitem' <-- You Are Here"
else
echo "[$MYCDTEMPitemNum]='$MYCDTEMPitem'"
fi
fi
MYCDTEMPitemNum=$(( MYCDTEMPitemNum + 1 ))
done
else
echo "- No history -"
fi


************ That's it! I suppose zip files would be nicer...

Tuesday, April 24, 2012

ó vs ó

(Wow, I can actually see the difference, when typed in this window!) ó vs ó ó vs ó ó vs ó
Maybe not... might just be antialiasing...
Anyhow.

Apparently MacOS's bash handles these differently in different cases.

Comparing the following two strings returns FALSE:

'Debaixo Dos Caracóis'
'Debaixo Dos Caracóis'

whereas comparing these two returns TRUE:

'Debaixo Dos Caracóis'
'Debaixo Dos Caracóis'

Duh!

The weird thing is that they come from the same source. The only difference is that one was entered directly with the filename (which contains this string) typed using tab-completion, and the other was entered via for-loop of all files in the directory. Seems like a bug to me, but what do I know?

Some investigating led to how to remove accents from characters: Source
It didn't work for me directly, I had to do some fiddling to get any conversion for the second string (otherwise it would return "iconv couldn't convert")

using the command echo "$string" | iconv -t UTF-7 I get the following two values:

'Debaixo Dos Carac+APM-is'
'Debaixo Dos Caraco+AwE-is'

So, apparently the two accented o's are coming up different, even though they appear the same! Again, oddly, if I run my script within a for loop iterating over all files in the directory, I get "o+AwE-" and if I use tab-completion on the command line I get "+APM-" and the strings match.

Further investigation reveals some useful info: printf can be run from the command line! Source


$ first=`echo "+APM-" | iconv -f UTF-7 -t UTF-8`
$ second=`echo "o+AwE-" | iconv -f UTF-7 -t UTF-8`
$ echo $first
ó
$ echo $second
ó
$ printf '%d\n' "'$first"
-61
$ printf '%d\n' "'$second"
111
$ if [ "$first" == "$second" ] ; then echo YEP ; fi
$

So there you have it... their values aren't even the same. Are they ASCII? I have no idea. This locale and Unicode and other codepage stuff completely eludes me. Here's the page that can tell you all about it. It's WAY over my head: Locale And it doesn't even seem there's such thing as a universal Unicode chart (like there is for 7-bit ASCII)

All I know is that my bash is set with a locale of en-US.UTF-8 and apparently that doesn't match the filenames on my hard drive (?!)

That "o+AwE-" is strangely remniscent of how accents (used to?) be entered on Macs way back in the OS7.5 days... first you typed the letter, then some combination of CTRL and whatnot. I was fascinated by it once and wrote a whole chart. The "+APM-" seems more like PC-style entering a value directly using ALT-###, but I could be imagining things.

This would make my whole project extremely more difficult, except I'd already been working on fuzzy string-matching for differences like McDonalds vs MacDonalds so thankfully I can use that instead of trying to figure out a table of special cases like this. Otherwise, frankly, I'd be at a complete loss as to how to procede without dropping the character entirely. Even the iconv locales don't seem to convert them to anything directly-comparable (only visually). Actually, it could still become a problem for filenames with too many accents... UGH

Monday, April 16, 2012

MP3 Spectrograms

Since MP3s are encoded by frequency-content, shouldn't it be *extremely fast* to convert an mp3 to a spectrogram? Utilities I've seen, so far, (such as sox) seem to convert it to samples first, then back to frequency-content.

---

Been looking into it, a bit. I think the reason this isn't highly-effective is because the actual frequency-content encoded into an MP3 bitstream is something like 32 (or 16?) samples... so even if a DCT is visualizable similar to a FFT spectrogram (which I have yet to find on the 'net), for an MP3 it would only be 32 frequencies tall (including DC), (and *really* wide). I can't quite wrap my head around all this, but I think that's the jist. So, I guess lower frequencies appear DC in these small snippets.

Also, there's something about frequency subbands and long vs short blocks which I can't wrap my head around, either. From what I can piece together from the libmad code, the inverse-DCT seems to be performed directly on small chunks, written directly into an array of samples. I can't figure out where the subbands come into play, nor if they somehow overlap... (which would, I presume, imply "sampleArray[i]+=" instead of "sampleArray[i]=").

This wasn't my original intent, but my original project takes literally 24 hours to process 7GB worth of music... so I guess it was a worthy venture to look into.

Wednesday, April 11, 2012

Script-fu

I shoulda known it would be slow... but this is absurd. A much more complex program in C processes this image in less than a minute... Script-fu's been running for over an hour and is only at 10%.

That's what I get for spending two days learning a new language. I shoulda known by "script" in the title...

Monday, April 9, 2012

"Preparing to remove partition"

I briefly tried Ubuntu on my PowerBook G4 and haven't touched it since, so decided it was time to free up those partitions for MacOS.

Enter the problem... Click the partition in Disk Utility, click the minus button, and apply... and it hangs, forever, no messages in the log, just hangs at "Preparing to remove partition." Even tried booting from the MacOS Install CD, same thing. There're quite a few posts about this online. Most seem to think that using Ubuntu's partition manager somehow caused the problem... Most suggest backing everything up and writing a fresh partition table from Disk Utility on the MacOS Install CD, then doing a restore from the backup. Others suggest using linux's partition utilities from now on... (which is silly if you're trying to *remove* linux).

I've figured out a trick, I guess... resize a partition (using Disk Utility). Not sure if it matters which one... as long as it's possible to resize it. Best-bet, erase/reformat the unwanted (ubuntu) partition into a Mac resizeable format (Mac OS Extended, Case-sensitive, Journalled, in my case). Resize that partition to something smaller. Afterwards it seems to delete partitions as expected. (Hopefully I didn't jinx myself by saying that and it still boots next time!)

----

Turns out it's a tad more complicated if you want to do more than just delete the partition (and why would you want to do that, instead of just reformatting, unless you planned to make new partitions of different sizes, or merge two partitions, etc?).

In my case, the Ubuntu partition was somewhere in the middle of the drive, and I wanted to merge it with later partitions to make one large partition. (This is a feat in itself, because merged partitions will only keep the data from the first in the partition-list... read below) Here's a link that got me started: http://macheist.com/forums/viewtopic.php?id=15828, and another: http://ubuntuforums.org/showthread.php?t=1181936

First: Run "diskutil list" from the terminal... (and "man diskutil"!)

And, a handy trick I discovered in the first link, create a blank disk-image, create a partition-table similar to the one you're planning to modify, and try everything you're planning to attempt inside that disk-image first. (Handy for making sure the merge command is going to keep the files on the first partition, among other things... like discovering that "eraseVolume" does not erase the volume from the partition table, but reformats it.).

The problem with creating a new partition and/or merging, at this point, arose because of the *hidden* "Boot OSX" partitions located before each partition, and the "Apple_bootstrap" partition created by ubuntu. These were not deleted with the deleted partition(s) with which they were associated, and are located in the space that otherwise appears empty. "Partition failed with the error: MediaKit reports partition (map) too small." I have no idea how Apple even thought the resize function could work in this case... (I can't recall how, but long ago I set up Disk Utility to show hidden partitions. This can also be done via diskutil in terminal).

As I recall, I ended up reformatting the BootOSX partitions into a usable-viewable format, then merging into/past them (more on merge later). Alternatively, and more intuitively, after reformatting (in Disk Utility, if you can figure out how to show hidden partitions), they'll show up in the partition-list and can be deleted. BEWARE: The BootOSX partition associated with your OSX partition is *necessary for booting* so be sure you know what you're doing! As far as I can tell, the "Boot OSX" partition that's located *immediately before* the OSX partition is the one that boots it, but I don't know this for certain for all cases.

As for merging two (or *multiple*) partitions, look into the man-page for diskutil. (The terminal command is: diskutil merge "format type" "name" disk#s# disk#s#) The format-type and name are necessary, even if you're not planning to reformat, it doesn't seem to affect the drive if everything's right.

Notes: I'm running 10.5.8 (Leopard? Tiger? Bobcat? Puma? I have no idea) on a PowerPC G4. These BootOSX partitions may vary a bit on intel, I don't know. Also: "Disk Utility" is the one located in Applications/Utilities/Disk Utility, and "diskutil" is a terminal (command-line) program akin to fdisk with a bunch more features).

Hope this helps someone!