You are not logged in.

#1 2011-02-22 08:14:29

upsidaisium
Member
From: Vietnam
Registered: 2006-09-16
Posts: 263
Website

Shell script blog -OR- Give me tips on how to write better scripts!

Hi folks,

I don't write a lot of shell scripts, and the ones that I do write are usually quite short, so as a learning exercise I made a shell/CGI blog script.. And I was hoping that some of the shell scripting experts in the community could give me some pointers on form, style, etc! The script works just fine, but maybe I haven't coded it very elegantly. Or maybe in some places I haven't necessarily used the right (or most appropriate?) commands to accomplish what I want.

It's a simple blog. It can either:
- Display a blog post (by default the newest, unless the name of a post is given)
- Display a listing of posts for a certain tag

Posts are saved in normal files in markdown format. Tagging is accomplished by putting the name of the tag(s) into the filename, separated by hyphens. For example: the file "wonderful_blog_post-whining-computers-archlinux.md" would be a post named "wonderful blog post", and it would have three tags ("whining", "computers", "archlinux"). Maybe it's not the best idea in the world... but I went with it anyhow smile

I put the script on pastebin for you all to see: http://pastebin.com/L8nMpUjT

Please do take a look and let me know if I've done something badly! Hopefully I can learn a thing or two from your comments.

And there's a working example of it here: http://www.ynnhoj.net/thedump/s.cgi


I've seen young people waste their time reading books about sensitive vampires. It's kinda sad. But you say it's not the end of the world... Well, maybe it is!

Offline

#2 2011-02-22 16:22:18

freak
Member
Registered: 2009-04-15
Posts: 17

Re: Shell script blog -OR- Give me tips on how to write better scripts!

http://mywiki.wooledge.org/BashGuide
http://mywiki.wooledge.org/BashFAQ/001

I would guess that you learned from the so-called "Advanced" bash guide, which is pretty terrible to be honest.

The biggest issue I've seen is using "for" to iterate through the output of a command.  As FAQ 1 (the second link) explains, this should never be done.  It makes for really fragile code.

There is also a lack of quoting, and ls should never be in a script.  See http://mywiki.wooledge.org/ParsingLs and http://mywiki.wooledge.org/BashPitfalls

I hope this helps...  I don't mean to tear this apart or anything, but you asked for criticism, and there it is.  Good luck with this, and I hope you can turn it into much more robust code using this guide.

Offline

#3 2011-02-23 01:16:13

upsidaisium
Member
From: Vietnam
Registered: 2006-09-16
Posts: 263
Website

Re: Shell script blog -OR- Give me tips on how to write better scripts!

I don't mind criticism as long as it's constructive smile Like I said before, my script works but I wasn't if I had actually coded it well!

I haven't read any guides, by the way. I've just patched this together using the bit of sh knowledge that I already have and by looking at scripts (of all sorts) that other people have written to learn more.

I'll take a look at the links you've provided and try to make the changes that you've suggested. Regarding using ls, I was pretty sure that I shouldn't be using it. But what about this line:

ls -t $(find -iname '*.md' | sed 's,^\./,,')

In this context would using ls be acceptable? And if not, how can I use find (or some other command) to sort my files by the modification time?

Thanks!

Edit: Another question, if you don't mind, regarding using a while loop. This works for me:

find . -name "*.md" | sed -e 's,\./,,' | while read -r post; do
        echo $post
done

So.. would you consider this the preferred way to do it?

Last edited by upsidaisium (2011-02-23 01:52:50)


I've seen young people waste their time reading books about sensitive vampires. It's kinda sad. But you say it's not the end of the world... Well, maybe it is!

Offline

#4 2011-02-23 01:58:03

falconindy
Developer
From: New York, USA
Registered: 2009-10-22
Posts: 4,111
Website

Re: Shell script blog -OR- Give me tips on how to write better scripts!

To sort files by modification time (safely) requires GNU stat and some bash:

declare -a files
while IFS=$'\t' read -r -d '' ts file; do
  files+=("$file")
done < <(stat --printf '%Y\t%n\0' * | sort -zn)

printf "%s\n" "${files[@]}"

The array is of course unnecessary as you could print inside the loop, but I see no way around the usage of null delimiters and bashisms (read's -d flag in particular) to be 100% safe.

Offline

#5 2011-02-23 02:20:10

sisco311
Member
From: Romania
Registered: 2008-05-23
Posts: 112

Re: Shell script blog -OR- Give me tips on how to write better scripts!

upsidaisium wrote:

Another question, if you don't mind, regarding using a while loop. This works for me:

find . -name "*.md" | sed -e 's,\./,,' | while read -r post; do
        echo $post
done

So.. would you consider this the preferred way to do it?

I think, the preferred method is:

while IFS= read -rd '' file; do
  file="${file##*/}"  # or file="${file#*/} # I'm not sure if I fully understand your code :)
  echo "$file"
done < <(find . -name '*.md' -print0)

But, please check out the links posted by freak or  seek for answers on the #bash channel on freenode.

Last edited by sisco311 (2011-02-23 02:28:30)


don't drink unwashed fruit juice.
i never make predictions, especially about the future.

Offline

#6 2011-02-23 06:43:28

upsidaisium
Member
From: Vietnam
Registered: 2006-09-16
Posts: 263
Website

Re: Shell script blog -OR- Give me tips on how to write better scripts!

falconindy wrote:

To sort files by modification time (safely) requires GNU stat and some bash:

declare -a files
while IFS=$'\t' read -r -d '' ts file; do
  files+=("$file")
done < <(stat --printf '%Y\t%n\0' * | sort -zn)

printf "%s\n" "${files[@]}"

The array is of course unnecessary as you could print inside the loop, but I see no way around the usage of null delimiters and bashisms (read's -d flag in particular) to be 100% safe.

Thanks for the example, though I'm trying to avoid bash and write my script in posix shell. So after some tinkering, this is what I've come up with to make a simple list of blog post file names:

#!/bin/sh

cd posts

while IFS=$'\t' read -r ts file; do
        ALLPOSTS="$ALLPOSTS $file"
done << EOF
$(stat --printf '%Y\t%n\n' *.md | sort -rn)
EOF

echo $ALLPOSTS

So I suppose that it isn't 100% safe - but could it be acceptable? Is there anything else I could do?

Edit: as it turns out, my server is running some flavour of BSD, I think FreeBSD. So the above examples don't work with FreeBSD's stat. Ah well..

Last edited by upsidaisium (2011-02-23 08:26:29)


I've seen young people waste their time reading books about sensitive vampires. It's kinda sad. But you say it's not the end of the world... Well, maybe it is!

Offline

#7 2011-02-23 17:56:20

freak
Member
Registered: 2009-04-15
Posts: 17

Re: Shell script blog -OR- Give me tips on how to write better scripts!

It's possible to get the newest file from a directory using nothing but POSIX shell (assuming [ has -nt, think it does). 

latest() {
  local file latest
  for file in "{1:-.}"/*; do
    [ "$file" -nt "$latest" ] && latest=$file
  done
  printf "%s\n" "$latest"
}
latest [dir]

Actuall sorting by mtime is a really tricky issue though... it's enough of a pain with bash and GNU coreutils as it is.

Last edited by freak (2011-02-23 17:58:32)

Offline

Board footer

Powered by FluxBB