34

Find an unused drive letter

Your task is to write the shortest code to find one of the unused drive letters (excluding a,b and c). PowerShell’s default aliases are allowed. You have one week.  Answers should be posted as a comment to this brain teaser. That’s it.


The winner gets a copy of  the “VMware vSphere PowerCLI Reference” from Sybex!

We’ll post clues over the next couple days, stay tuned.

Good Luck!

 

[UPDATE] 1/23/2012

We have a winner: P!
Your code was 36 characters long:

for($j=67;gdr($d=[char]++$j)2>0){}$d

This is the breakdown of our solution (47 characters):

ls function:[d-z]: -n|?{!(test-path $_)}|random

We took a different approach (though more lengthy) to get a list of available by listing the default A-Z functions and using the Name switch to get the names only.
We then tested if a drive with the incoming drive letter name was available, if so, it was written back to the pipeline.
Finally, we used the Get-Random cmdlet to choose for us an available letter. As you can see we called Get-Random by its verb only. You may suspect that ‘random’ is an alias for that command but it isn’t. We used a known trick to shorten Get-Random – when PowerShell cannot resolve a command it tries to resolve it again by prepending the Get verb.

We hope you had fun and that you enjoyed participating and was able to learn a thing or two. See you in the next brain teaser.
We also would like to thanks our sponsors, Sybex, for giving away the book for the Winner.

 

Filed in: Brainteasers Tags: , , ,

2 Pingbacks/Trackbacks

  • http://jrich523.wordpress.com/ jrich

    68..90|%{$l=gwmi win32_volume|%{$_.driveletter -replace “:” }}{if($l -notcontains [char]$_){[char]$_}}
    -jrich
    http://jrich523.wordpress.com

  • P.

    68..90 | % { $d = [char]$_; if (!(gdr $d -erroraction SilentlyContinue)) { $d; break; }}

  • Emin

    68..90|%{if(!(gdr ([char]$_) -EA 0)){[char]$_;break}}

  • Emin

    68..90|%{$d=[char]$_;if(!(gdr $d -EA 0)){$d;break}}

  • P.

    68..90|%{[char]$_}|%{if(!(gdr $_ -EA 0)){$_;break}}

  • P.

    [char[]](68..90)|%{if(!(gdr $_ -EA 0)){$_;break}}

    49 characters!

  • http://jrich523.wordpress.com/ jrich

    33!
    [char[]](68..90)|?{!(gdr $_ -ea 0)}

    • P.

      Not the same; it shows all free drives, not ‘one of’ …

  • Simone

    [char[]](68..90)|%{if(!(gdr $_)){break}}

    • Joe

      Your script fails with an error

      • Simone

        but this error shows first unused driveletter :-)

  • P.

    if failure is an option, it can be done in 35

    [char[]](68..90)|%{$x=gdr $_ -ea 1}

  • http://jrich523.wordpress.com/ jrich

    ([char[]](68..90)|?{!(gdr $_ -ea 0)})[0]

    38 with error checking

    • Joe

      Not an option, it executes the gdr for eacy char in the array …

  • http://jrich523.wordpress.com/ jrich

    ([char[]](68..90)|?{!(gdr $_ -ea 0)})[0]

    38 with error checking

  • http://twitter.com/jamesoneill James O’Neill

    I can’t improve on JRich’s 38 chars to meet the original spec.
    But I can over come Joe’s objection in 44.

    for($j=67;gdr([char]$j)-ea 0){$j++};[char]$j

    • Makovec

      This is nice :) Like the different approach.

  • Jeff Lubar

    seems to work just fine for me… good job!

    PS C:UsersJeffrey> [char[]](68..90)|?{!(gdr $_ -ea 0)}FGHIJKLMNOPQRSTUVWXYZPS C:UsersJeffrey>

  • Makovec

    Get-PSDrive is not showing hidden drives (for example the one for AppV client), so had to use WMI. Running XP, so can’t use Win32_Volume:

    ([char[]](68..90)|?{@(gwmi win32_LogicalDisk|%{($_.deviceid)[0]}) -notcontains $_})[0]

    BTW – I like the idea of short contests (not necessary with prizes). But please – not on Friday when I am busy in the office :))

  • http://twitter.com/ShayLevy ShayLevy

    Hey all

    Thanks for participating, you rock! A few comments and clarifications:

    1. Your answer should not generate an error.

    2. You need to output just one drive letter (with or without a colon).

    3. @jrich, the following is 40 char long, not 38 (and if you’re out of letters it may fail):  
    ([char[]](68..90)|?{!(gdr $_ -ea 0)})[0]

    4. @makovec, initially we didn’t think about AppV drives so we can’t change the requirements now :)

    5. Our one-liner answer is 47 characters  long.

    6. Keep’em coming!

  • P.

    Going further with James’s idea

    for($j=67;gdr([char]++$j)-ea 0){}[char]$j

  • Emin

    Other ideas:

    ([char[]](68..90)|?{@(mountvol|Select-string “[A-Z]:\”|%{$_.toString().Trim()[0]}) -notcontains $_})[0]
    ([char[]](68..90)|?{@([system.io.DriveInfo]::GetDrives()|%{($_.Name)[0]}) -notcontains $_})[0]
    ([char[]](68..90)|?{@([io.Directory]::GetLogicalDrives()|%{($_)[0]}) -notcontains $_})[0]
    ([char[]](68..90)|?{@([io.DriveInfo]::GetDrives()|%{($_.Name)[0]}) -notcontains $_})[0]
    ([char[]](68..90)|?{@(wmic logicaldisk get name|%{($_)[0]}) -notcontains $_})[0]
    net use ((((net use * \DCsysvol) -split “`n”)[0]).substring(6,1)+”:”) /d
    # based on: http://powershell.com/cs/blogs/tips/archive/2009/10/21/find-next-available-drive-letter.aspx
    (68..90|%{“$([char]$_):”}|?{([IO.DriveInfo]$_).DriveType -eq ‘noRootdirectory’})[0]
    [char]([int][char](gdr -PS FileSystem)[-1].Name+1)

  • Pingback: Episode 172 – vCenter Orchestrator « PowerScripting Podcast

  • P.

    for($j=67;gdr($d=[char]++$j)-ea 0){}$d

  • Bluraydisk

    Great exercise, it cost me whole morning, but learn a lot.
    Thanks, Claudio

  • Elimelek

    # 37 chars:
    for($j=67;gdr($d=[char]++$j)2>$e){}$d

    # pipeline approach, 38 chars:
    ([char[]](68..90)|?{!(gdr $_)})[0]2>$e

  • P.

    36

    for($j=67;gdr($d=[char]++$j)2>0){}$d

    • Elimelek

      That writes to disk though ;)

  • Elimelek

    # 32 chars, implicit cast through the left hand rule:
    [char](1+[char](gdr ?)[-1].name)

    • Elimelek

      # 36 chars, globbing avoids error handling:
      ([char[]](68..90)|?{!(gdr [$_])})[0]

  • Elimelek

    Is the contest still open for one last trick?

    # 24 chars:
    [char](1+”$(gdr ?)”[-1])

  • http://twitter.com/bielawb Bartek Bielawski

    IMO gdr can lead to wrong results… prefer WMI/ .NET solutions. I just created ‘E’ drive that points to my registry and most of scripts here show F as first available letter. ;) Solutions that assume that first available = next in alphabet after last used fail miserably, because I have virtual cd ‘Z’ ;)
    My 2 attempts (I admit, I was using Emim’s ideas a lot:
    ([char[]](68..90)|?{!((gwmi cim_logicaldisk)-match”=.$_”)})[0]
    ([char[]](68..90)|?{!([io.driveinfo]::GetDrives()-match$_)})[0]

    This code is awful to read (kill me for using -match in such a way, I deserve it ;)).
    And most likely has other flaws that in turn I missed. :>

    • Elimelek

      Unless otherwise indicated, brainteasers – and their solutions – should be set in a common and leveled field, i.e. a non-profile powershell session. Having said that, I don’t think many systems would have ‘Z’ logical drive by default

  • Pingback: PowerShell Magazine » #PSTip Get next available drive letter

© 2014 PowerShell Magazine. All rights reserved. XHTML / CSS Valid.
Proudly designed by Theme Junkie.
%d bloggers like this: