From The Archives: 2008
I was messing around in bash, trying to create a script template that would include all the things that I normally use when writing bash scripts. You know, common functions you re-write every time you write a script, variables etc. It’s also nice to use a template so when you or some-one else goes back to it later, everything is more, or less in the same area you expect it.
Well, I figured that I would like to create a standard variable I’d use when writing scripts, that would place all logs, data files etc into a similar path for each script, and needed to create a basefolder (as in the opposite of basename) . And for the record, this was for a string, not an actual folder path. (As in, there was no basename to sed out from a $PWD etc)
If I had a variable I was using say for example:
and wanted to know if the last folder in this string exists , I thought I could do a command like so to get the upper part of that string:
folder_path=`echo -n “$var” | sed ‘s/\//\n\//g’ | tac | sed ‘1,1d’ | tac | sed ‘s/\n//g’` ;
Which in English, translates to: Echo the variable to sed which will replace each occurrence of a forward-slash with a newline and a forward-slash, then reverse order the new lines and delete the first line it sees, reverse order again, and join the lines into one line by deleting the newlines sed made in the first place.
The first mistake bash programmer do is to test out lines of bash scripting code in terminal, I know this, yet, I do it all the time. Bash code lines do not always work the same way as they do within a script file. Part of the reason for this is the way you cut and paste your code from the editor you are using into terminal, and the way the terminal views newlines.
Via the terminal, my command does this…(However, testing it inside a an actual a script didn’t help much.)
bash$ folder_path=`echo -n $tmp | sed ‘s/\//\n\//g’ | tac | sed ‘1,1d’ | tac | sed ‘s/\n//g’` ;
bash$ echo “$folder_path”
First off, the last two folders are missing, not just one as I had wished. In addition, sed didn’t delete the newlines it created.
I split the command into parts and cut out parts that worked till I found this odd thing….
echo -n $tmp | sed ‘s/\//\n\//g’ | sed ‘s/\n//g’
This command above, should do NOTHING. Basically, my human logic tells me that I am attempting to tell the terminal to echo the variable ‘tmp’ without new lines and replace forward-slash with a newline and a forward-slash, then remove the newlines, in other words nothing. In terminal, this results in the following output:
bash$ echo -n $tmp | sed ‘s/\//\n\//g’ | sed ‘s/\n//g’
As you can see, the new lines that sed created are not erased. Everything else is exactly the way I wanted it. But inside a script, the results are as follows: (new variable added ./test.sh content below)
new=`echo -n $tmp | sed ‘s/\//\n\//g’ | sed ‘s/\n//g’` ;
echo $new ;
/home /user /mainfolder /wantedfolder /missingfolder
It’s enough to shake your head at. However, after trying to seek help from both my brother, and LXPK, (it stumped both of them too), I started to get a feeling about what was going on.
And here is the weird part…
folder_path=`echo -n “$var” | sed ‘s/\//\n\//g’ | tac | tail -9999 | tac | sed ‘s/\n//g’` ;
Notice the ‘tail -9999‘, I’m pretty sure that in the back of brain is the answer to all this, but it is completely slipping my mind at the moment. Because this flipped the last folder with the second part I was fooled into thinking it worked, (assuming I’d just add a joining part to the script). But I note it here because it could be a neat bash trick, useful someday.
Maybe I’ll fix it tomorrow.