Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

How can we write a script around dscl to loop over the currently listed IDs in use and then spit out the first id under 500 that is not in use yet?

Update # 1 (Feb 17th 2013)

I found some very helpful scripts on http://wiki.awkwardtv.org/wiki/Manage_users_and_groups_scripts which I was able to water down to the point where I could get the first available ID higher than a given number but I still don't have a way of scripting it to stop looking beyond a certain upper limit like 500.

#!/bin/sh
continue="no"
number_used="dontknow"
fnumber=300
user_id=0
until [ $continue = "yes" ] ; do
  if [ `dscl . -list /Users UniqueID | awk '{print $2, "\t", $1}' | sort -ug | grep -c "$fnumber"` -gt 0 ] ; then
    number_used=true
  else
    number_used=false
  fi
  if [ $number_used = "true" ] ; then
    fnumber=`expr $fnumber + 1`
  else
    user_id="$fnumber"
    continue="yes"
  fi
done;
echo "Next available user_id: $user_id"

Update # 2 (Feb 17th 2013)

I suppose I could work backwards but still what if every userid from 500 to 0 is taken? I still need to set a lowerbound to get out of a messy negative ID situation.

#!/bin/sh
continue="no"
number_used="dontknow"
fnumber_work_backwards_from=500
fnumber=$fnumber_work_backwards_from
user_id=0
until [ $continue = "yes" ] ; do
  if [ `dscl . -list /Users UniqueID | awk '{print $2, "\t", $1}' | sort -ug | grep -c "$fnumber"` -gt 0 ] ; then
    number_used=true
  else
    number_used=false
  fi
  if [ $number_used = "true" ] ; then
    fnumber=`expr $fnumber - 1`
  else
    user_id="$fnumber"
    continue="yes"
  fi
done;
echo "First available user_id which is closest to and lower than $fnumber_work_backwards_from: $user_id"
share|improve this question
    
Did you see my answer when you updated the question? (I undeleted it, maybe it didn't show up) –  slhck Feb 17 '13 at 15:56
add comment

1 Answer

up vote 0 down vote accepted

This can be done with Ruby, for example, which is much more concise than any Bash script you could possibly find for this.

dscl . -list /Users UniqueID | awk '{print $2}' | 
ruby -e 'puts ((0..500).to_a - STDIN.readlines.map(&:to_i)).first'

We simply subtract the actual IDs (as an array) from another array consisting of the numbers 0 through 500. This gives us all unused IDs in an array, and from that we take the first, since it's already sorted.

share|improve this answer
    
Not a language I can use in my infrastructure but you answered the Q :) –  pulkitsinghal Feb 18 '13 at 15:46
    
Oh, I didn't know that, sorry. OS X comes with Ruby though, or can't you use it for some other reason? Note that going with a set-based approach is often easier than lower level stuff—problem domain thinking, so to say :) –  slhck Feb 18 '13 at 17:01
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.